OpenMP: OpenMP测试程序

#include <omp.h> #include <stdio.h> int main(int argc, char * argv[]) {  int nthreads, tid, x;  int nthrds = 4;  x = 0;  omp_set_num_threads(nthrds); #pragma omp parallel private(tid)  {   tid = omp_get_thread_num();   printf("Hello world from OMP thread %d\n",tid);

 } #pragma omp parallel shared(x)  { #pragma omp critical   x = x + 1;  }  printf("x = %d \n", x);  return 0; }

result:


 

学习了OpenMP的使用方法,按照教程中的sample自己写了几个小代码。

我的理解就是OpenMP对并行计算进行了抽象,使得程序员能很容易的写出并行计算的代码,并解决了线程粒度和负载均衡的问题。对比与自己写多线程的代码,OpenMP更加简单。但是还是需要解决一些变量冲突等问题,例如将一个变量设置为私有。设置临界区等。

对比与CUDA,OpenMP首先是CPU多线程,不需要拷贝数据到GPU,在数据量不大的时候应该会比CUDA有优势,CUDA拷进拷出就会浪费不少时间。

其中工作量的划分与调度的三种方式很有意思:(抄袭自OpenMP入门.pdf)

1、 静态:把循环的迭代按照每x次(x=chunk)迭代分为一块,这样你的总工作量就被划分成了n/x块(n为迭代次数、循环次数),然后将这些块按照轮转 法依次分配给各个线程。举个例子:比如我们有100次迭代,x=chunk=4,那么我们的工作就被分为25块,假设我们有2个线程可以做工作,那么线程 1分到的块是1,3,5,7....,25,
线程2分到的块是2,4,6,...,24;
2、动态:迭代分块方法同上,但是工作块被放到一个队列中,每个线程每次拿一块,做好了才能到队列里去拿下一块;
3、Guided:这个方式是动态方式的改进。在这个方式里,分块的x是不固定的,一开始块的大小(x)比较大,随着剩余工作量的减小,块的大小也随之变小。
静态方式:比较适合每次迭代的工作量相近(主要指工作所需时间)的情况
动态方式:比较适合每次迭代的工作量非常不确定的情况
Guided方式:类似动态方式,但是队列相关的开销会比动态方式小

下面是写的一些小例子

#include <stdio.h>

void* work(float* c,int N);
void add();
float dotProdWrong(float* a,float* b,int N);
float dotProdRight(float* a,float* b,int N);
double getpi();
float a[3]={1.0,2.0,3.0};
float b[3]={1.0,2.0,3.0};


static long numsteps=10;
double step,pi;
int main()
{
//#pragma omp parallel
	printf("hello word!\n");
	//work(c,3);
	//dotProdWrong(a,b,3);
	//dotProdRight(a,b,3);
	getpi();
	return 1;

}

void add()
{
	int i;
#pragma omp  for
	for(i=0;i<6;i++)
	{
		printf("iter:%d\n",i);

	}
		printf("good bye word!\n");
}
void* work(float* c,int N)
{
	float x,y;
	int i;
#pragma omp parallel for private(x,y)
	for(i=0;i<N;i++)
	{
		x=a[i];
		y=b[i];
		c[i]=x+y;
	printf("work inside:%d\n",c[i]);
	}
	return NULL;
}

float dotProdWrong(float* a,float* b,int N)
{
	float sum=0.0;
#pragma omp parallel for shared (sum)
	for(int i=0;i<N;i++)
	{
		sum+= a[i]*b[i];
		printf("dotProdWrong inside:%d\n",sum);	
	}
	printf("dotProdWrong last:%d\n",sum);
	return sum;
}

float dotProdRight(float* a,float* b,int N)
{
	float sum=0.0;
#pragma omp parallel for shared (sum)
	for(int i=0;i<N;i++)
	{
#pragma omp critical
		sum+= a[i]*b[i];
		printf("dotProdRight a:%f\n",a[i]);
		printf("dotProdRight b:%f\n",b[i]);
		printf("dotProdRight inside:%f\n",sum);	
	}
	printf("dotProdRight last:%f\n",sum);
	return sum;
}

//递归 redunction,计算sum的和值
//#pragam omp parallel for reduction (+,sum)

double getpi()
{
	int i;
	double x,sum=0;
	step=1.0/(double)numsteps;
#pragma omp parallel for reduction (+:sum)
	for( i=0;i<numsteps;i++)
	{
		x=(i+0.5)*step;
		sum=sum+4.0/(1.0+x*x);
		printf("sum=%f\n",sum);
	}
	pi=step*sum;
	printf("pi=%f\n",pi);
	return pi;
}
//#pragam omp single 确保一个线程
//#pragam omp master 确保主线程执行
//debug openmp api
//icl /Qopenmp testOpenMp.cpp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值