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