主要在vs2015下使用OMP,写一些自己omp的学习心得:
一、在VS2015下OpenMP的使用:
1、VS2015也仅仅支持OpenMP2.0版本,VS对OpenMP的支持并不太好。
2、在VS下使用OPenMP需要在项目设置中找到,项目-->语言-->OpenMP支持中,选择是,下图所示:
并且在头文件中包含"omp.h"即可支持OpenMP了。
二、关于数据属性
1、shared 用来声明一个或者多个共享变量,在并行区会有数据竞争。
2、private 声明私有变量。
1 void test_private() 2 { 3 printf("--before parallel-------------- "); 4 int a =100 ; 5 printf("a=%d ", a); 6 printf("--parallel-------------- "); 7 #pragma omp parallel for private(a) 8 for (int i = 0; i < 10; i++) 9 { 10 a = i;//如果a没有被初始化,会提示a没有初始化,即使在并行前做了初始化也会有错误! 11 printf("a=%d ", a); 12 } 13 printf("--after parallel-------------- "); 14 printf("a=%d ", a); 15 }
结果输出:
--before parallel-------------- a=100 --parallel-------------- a=0 a=6 a=8 a=1 a=2 a=5 a=9 a=3 a=4 a=7 --after parallel-------------- a=100
3、default default(shared):表示并行区域内的共享变量在不指定的情况下都是shared属性;default(none):表示必须显式指定所有共享变量的数据属性,否则会报错,除非变量有明确的属性定义(比如循环并行区域的循环迭代变量只能是私有的。
4、firstprivate 继承并行区域之外的变量的值,用于在进入并行区域之前进行一次初始化。
void test_firstprivate() { printf("--before parallel-------------- "); int a = 100; printf("a=%d ", a); printf("--parallel-------------- "); #pragma omp parallel for firstprivate(a) num_threads(3) for (int i = 0; i < 10; i++) { printf("ID=%d,i=%d,a=%d ",omp_get_thread_num(),i,a); a = i;//对于某个线程来说,firstprivate仅仅进行一次初始化 } printf("--after parallel-------------- "); printf("a=%d ", a); }
结果如下:
--before parallel-------------- a=100 --parallel-------------- ID=0,i=0,a=100 ID=0,i=1,a=0 ID=2,i=7,a=100 ID=0,i=2,a=1 ID=1,i=4,a=100 ID=2,i=8,a=7 ID=0,i=3,a=2 ID=2,i=9,a=8 ID=1,i=5,a=4 ID=1,i=6,a=5 --after parallel-------------- a=100
5、lastprivate 如果需要在并行区域内的私有变量经过计算后,在退出并行区域时,需要将其值赋给同名的共享变量,就可以使用lastprivate完成。
1 void test_lastprivate() 2 { 3 printf("--before parallel-------------- "); 4 int a = 100; 5 printf("a=%d ", a); 6 printf("--parallel-------------- "); 7 #pragma omp parallel for lastprivate(a) num_threads(3) 8 for (int i = 0; i < 10; i++) 9 { 10 a = i; 11 printf("ID=%d,i=%d,a=%d ", omp_get_thread_num(), i, a); 12 13 } 14 printf("--after parallel-------------- "); 15 printf("a=%d ", a); //获得逻辑上a的最后一个值,而不是最后一个线程的a值 16 }
结果如下:
--before parallel-------------- a=100 --parallel-------------- ID=0,i=0,a=0 ID=0,i=1,a=1 ID=1,i=4,a=4 ID=2,i=7,a=7 ID=0,i=2,a=2 ID=2,i=8,a=8 ID=1,i=5,a=5 ID=0,i=3,a=3 ID=1,i=6,a=6 ID=2,i=9,a=9 --after parallel-------------- a=9
6、threadprivate 指定全局变量被OpenMP所有的线程各自产生一个私有的拷贝,即各个线程都有自己私有的全局变量。一个很明显的区别在于,threadprivate并不是针对某一个并行区域,而是整个于整个程序,所以,其拷贝的副本变量也是全局的,即在不同的并行区域之间的同一个线程也是共享的。threadprivate只能用于全局变量或静态变量。
7、copyin 用于将主线程中threadprivate变量的值拷贝到执行并行区域的各个线程的threadprivate变量中,从而使得team内的子线程都拥有和主线程同样的初始值。copyin中的参数必须被声明成threadprivate的。
8、copyprivate用于将线程私有副本变量的值从一个线程广播到执行同一并行区域的其他线程的同一变量。copyprivate只能用于single指令的子句中,在一个single块的结尾处完成广播操作。copyprivate只能用于private/firstprivate或threadprivate修饰的变量。