Open mp在cpu上并行计算,
统一内存访问(OPEN MP pthreads),同一块内存共享多个CPU
非统一内存访问(MPI),每个CPU都有自己对应的内存,通过blus interconnect链接起来,cpu不能直接访问他们的内存,需要进行通信才可以访问到他们所属的memory,
OPEN MP pthreads他们都是针对共享内存编程的API
哪个线程要指定
Open mp,只加简单的预定义,编译器自动编译并行,
Open mp开始运行时候,有一个master thread 主线程(串行执行的)执行—并行(分开了fork),同步,合并,
有一些编译器不支持open mp,加入pragma让编译器暂时不用管这个语言规范
获取将要派生的线程的数量,在main函数里,strtol可以获取在程序执行时候获得的一些参数
pragma omp parallel num threads(thread_count)
Hello();
并行执行hello();
Pragma用了这个语句表示这个可能在c中是不被接受的
omp parallel,告诉他我们要使用omp的并行化
num threads(thread_count) 我们要并行的数量有多少个
int my_rank = omp_get_thread num();当前我们创建的线程是排第几个,比如一共有4个线程创建的,那么这个可能的取值就是0,1,2,3,也是线程id
int thread count = omp_get_num threads();当前我们创建的线程总数,按着上边的例子就是4
openmp for
在for(int i=0;i<1000;i++)中,线程也是比较均匀分配的,可能,线程0:0-249;线程1:250-499;线程2:500-749;线程3:750-1000
均等分配,同时并行执行的
比如要用,fibo[i-1],fibo[i-2],他们如果还没计算出来,就不会得到正确的输出,数据依赖会导致结果错误。
OpenMP编译器不检查被parallel for指令并行化的循环所包含的迭代间的依赖关系
个或者更多个迭代结果依赖于其他迭代的循环,一般不能被正确的并行化
openmp private variables
变量在并行块外定义,也可以在并行中调用
对于线程0,可能tmp的值是2,对于线程1,tmp的值为3,1比0慢一点,那么当线程0执行到c[i]的时候此时的结果是3*3,不对应于0线程对应的2的tmp值
这样定义了以后,每个线程都有tmp,
关于private的信息
每一个线程都是拥有独自的该变量的副本
如果i被定义为私有变量,那么在for循环里面,所有的线程都不能访问其他(尽管i是共享变量)
所有的线程都不会使用到先前的定义
所有线程都不能给共享的j赋值,(不会改变之前全局定义的j的值)
在循环的入口以及出口,都不会进行定义(私有的j只会在线程内部被定义使用)
Firstprivate
Firstprivate 选项告诉编译器私有变量在第一个循环会继承共享变量的值这个私有的变量只会在每个线程的第一个循环继承,而不会在每个循环中继承和
其使用方法于private几乎一致
#pragma omp parallel for lastprivate(x)
本来这个指针a指向0x1,后边改变一下指向0x2,对原来的值是没有影响的,但是要是修改了0x1指向的空间的值,其他线程也是可以看到这个修改的
lastprivate
用私有lastprivate 选项告诉编译器私有变量会在最后-个循环出去的时候变量的值替换掉我们共享变量的值
parallel语句
当负责最后一个iteration的线程离开循环的时候它会将该私有变量的值赋值给当前共享变量的值。
只有速度的差异没有代码执行量的差异
section选项
Reduction 归并
会把每一个线程的j加起来
j=10+10+20=40
Barrier
他是用于实现同步的一种手段他会在代码的某个点,令线程停下直到所有的线程都到达该地方
使用的语法如下
#pragmaomp barrier
阻塞在这个语句之前,等所有线程都到了再继续往下执行
许多情况下,它已经能够自动的插入到工作区结尾
比如说在for,single
但是它能够被nowait禁用