这是里把OpenMP常用的数据环境construct用代码示例的方法写出来了,主要包括private,firstprivate,lastprivate和copyin。注释部分对这几种construct作用和区别描述已经很详细了,这里就补多说,相信演示代码会有更好的效果。
// Data Environment.cpp : 定义控制台应用程序的入口点。 #include <stdio.h> #include <omp.h> int cpx = 100; // threadprivate只对全局或静态数据项有效 #pragma omp threadprivate(cpx) // 必须在main外 int main(int argc, char* argv[]) { int i, px, fpx, lpx; px = fpx = lpx = 100; cpx = 100; printf("\n--------------------------------private--------------------------------\n"); #pragma omp parallel for private(px) // threadprivate和private的区别是private只在并行区中有效,而threadprivate属性是全局范围内有效的。 for (i = 0; i < 5; i++) { px = 1000; // private构造px之后,包括主线程在内的所有变量px都是线程私有的,且需要从新初始化,否则运行出错。 px += i; printf("threadnum = %d, px = %d\n",omp_get_thread_num(), px); } printf("串行 threadnum = %d, px = %d\n",omp_get_thread_num(), px); // private构造的变量是线程局部的,退出并行去后线程变量自动销毁。这里是原来的串行区对应变量px,并且和下次进入并行区的变量无关。 printf("\n--------------------------------firstprivate-----------------------\n"); #pragma omp parallel for firstprivate(fpx) // 设变量属性为private,同时每个线程的这个变量的初始值为串行区对应变量的值,这样就不需要我们再次初始化。 for (i = 0; i < 9; i++) { fpx += i; // 这之前没有再次初始化fpx printf("threadnum = %d, fpx = %d\n",omp_get_thread_num(), fpx); } printf("串行 threadnum = %d, fpx = %d\n",omp_get_thread_num(), fpx); //同样,因为变量属性为private,是局部的,这里的fpx还是以前的(串行区对应变量),值并没有改变。 printf("\n--------------------------------lastprivate----------------------------\n"); #pragma omp parallel for lastprivate(lpx) // 最后一次迭代内的lastprivate变量的值将被带出并行区赋给串行区对应的同名变量,当然这个必须和for循环一起用,否则会出错。 for (i = 0; i < 9; i++) { lpx = 1000; // lastprivate构造lpx之后,变量lpx变成线程私有的局部变量,因此需要从新初始化,否则运行出错。 lpx += i; printf("threadnum = %d, lpx = %d\n",omp_get_thread_num(), lpx); } printf("串行 threadnum = %d, lpx = %d\n",omp_get_thread_num(), lpx); // lastprivate将最后一次迭代的变量值赋给了对应的全局变量,所以这里的lpx值变化了 printf("--------------------------------copyin parallel first--------------------\n"); cpx = 1000; #pragma omp parallel { printf("threadnum = %d, cpx = %d\n", omp_get_thread_num(), cpx); //threadprivate,主线程继承原来串行区的值,其他线程继承对应的全局变量的值。(串行区是由主线程执行的,就是说主 // 线程中的cpx值之前已被更改,而其他的未变) } printf("串行 cpx=%d\n",cpx); printf("--------------------------------copyin parallel second-------------------\n"); #pragma omp parallel copyin(cpx) // copyin: 把主线程(串行区)全局变量的值拷贝到各线程中同名的threadprivate变量中去。 { printf("copyin,threadnum = %d, original cpx = %d\n", omp_get_thread_num(), cpx); cpx = omp_get_thread_num(); printf("after change,threadnum = %d, copyin: cpx = %d\n",omp_get_thread_num(), cpx); } printf("串行 cpx=%d\n",cpx); printf("--------------------------------copyin parallel third--------------------\n"); #pragma omp parallel //threadprivate不同于private的是前者是全局有效的,再次进入并行区,使用的还是上次退出前赋予的值 printf("threadnum = %d, cpx = %d\n", omp_get_thread_num(), cpx); printf("串行 cpx=%d\n",cpx); return 0; }
结果如下: