这是里把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;
}
结果如下: