c++ openmp多线程编程


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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM