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