OpenMP Hello World
1 //omp.cc 2 #include <iostream> 3 #include <omp.h> 4 5 int main() 6 { 7 #pragma omp parallel for 8 for (char i = 'a'; i <= 'z'; i++) 9 std::cout << i << std::endl; 10 11 return 0; 12 }
编译:g++ omp.cc -fopenmp
检测是否支持 OpenMP
1 #ifndef _OPENMP 2 fprintf(stderr, "OpenMP not supported"); 3 #endif
omp_set_num_threads
1 #include <iostream> 2 #include "omp.h" 3 using namespace std; 4 int main(int argc, char **argv) { 5 //设置线程数,一般设置的线程数不超过CPU核心数,这里开4个线程执行并行代码段 6 omp_set_num_threads(4); 7 #pragma omp parallel 8 { 9 cout << "Hello" << ", I am Thread " << omp_get_thread_num() << endl; 10 } 11 }
#pragma omp parallel 和 #pragma omp parallel for
1 #include <iostream> 2 #include "omp.h" 3 4 using namespace std; 5 6 int main() { 7 omp_set_num_threads(4); 8 #pragma omp parallel 9 for (int i = 0; i < 3; i++) 10 printf("i = %d, I am Thread %d\n", i, omp_get_thread_num()); 11 return 0; 12 }
1 #include <iostream> 2 #include "omp.h" 3 4 using namespace std; 5 6 int main() { 7 omp_set_num_threads(4); 8 #pragma omp parallel for 9 for (int i = 0; i < 3; i++) 10 printf("i = %d, I am Thread %d\n", i, omp_get_thread_num()); 11 return 0; 12 }
private私有变量
private 子句可以将变量声明为线程私有,声明称线程私有变量以后,每个线程都有一个该变量的副本,线程之间不会互相影响,其他线程无法访问其他线程的副本。原变量在并行部分不起任何作用,也不会受到并行部分内部操作的影响。
1 int temp; 2 #pragma omp parallel for private(temp) 3 for (int i = 0; i < 100; i++) { 4 temp = array[i]; 5 array[i] = doSomething(temp); 6 }
firstprivate
private子句不能继承原变量的值,但是有时我们需要线程私有变量继承原来变量的值,这样我们就可以使用firstprivate子句来实现
1 int main(int argc, char* argv[]) 2 { 3 int t = 20, i; 4 #pragma omp parallel for firstprivate(t) 5 for (i = 0; i < 5; i++) 6 { 7 //次数t被初始化为20 8 t += i; 9 printf("t = %d\n", t); 10 } 11 //此时t=20 12 printf("outside t = %d\n", t); 13 return 0; 14 }
lastprivate
lastprivate子句在退出并行部分时将计算结果赋值回原变量
lastprivate必须要搭配firstprivate一起使用
需要注意的是,在循环迭代中,是最后一次迭代的值赋值给原变量;如果是section结构,那么是程序语法上的最后一个section语句赋值给原变量。
如果是类(class)变量作为lastprivate的参数时,我们需要一个缺省构造函数,除非该变量也作为firstprivate子句的参数;此外还需要一个拷贝赋值操作符。
1 int main(int argc, char* argv[]) 2 { 3 int t = 20, i; 4 // YOUR CODE HERE 5 #pragma omp parallel for firstprivate(t), lastprivate(t) 6 // END OF YOUR CODE 7 for (i = 0; i < 5; i++) 8 { 9 t += i; 10 printf("t = %d\n", t); 11 } 12 printf("outside t = %d\n", t); 13 return 0; 14 } 15 ===== OUTPUT ===== 16 t = 20 17 t = 24 18 t = 23 19 t = 21 20 t = 22 21 outside t = 24
shared
指定一个或多个变量为多个线程间的共享变量
reductions
一种常见的循环就是累加变量,OpenMP 有专门的语句reduction
OpenMP 为每个线程提供了私有的sum变量,当线程退出时,OpenMP 再把每个线程的部分和加在一起得到最终结果。
reduction支持“+,-,*,&,|,&&,||”
1 int sum = 0; 2 #pragma omp parallel for reduction(+:sum) 3 for (int i = 0; i < 100; i++) { 4 sum += array[i]; 5 }
critical
critical区域同一时间只能被一条线程执行
1 #include <iostream> 2 int main() { 3 int max = 0; 4 int a[10] = {11, 2, 33, 49, 113, 20, 321, 250, 689, 16}; 5 #pragma omp parallel for 6 for (int i=0;i<10;i++) { 7 int temp = a[i]; 8 #pragma omp critical 9 { 10 if (temp > max) 11 max = temp; 12 } 13 } 14 std::cout<<"max: "<<max<<std::endl; 15 return 0; 16 }
参考链接:
https://www.openmp.org/
https://www.cnblogs.com/ospider/p/5265975.html
https://blog.csdn.net/qq_40765537/article/details/106025514
https://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html
https://blog.csdn.net/billbliss/article/details/44131919