DSP

OpenMP: OpenMP学习的几个例子

2019-07-13 15:56发布

     学习了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 #include 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! "); //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 ",i); } printf("good bye word! "); } void* work(float* c,int N) { float x,y; int i; #pragma omp parallel for private(x,y) for(i=0;i