什么是OpenMP
Open Multi-Processing的縮寫,是一個應用程序接口(API),可用於顯式指導多線程、共享內存的並行性。
在項目程序已經完成好的情況下不需要大幅度的修改源代碼,只需要加上專用的pragma來指明自己的意圖,由此編譯器可以自動將程序進行並行化,並在必要之處加入同步互斥以及通信。當選擇忽略這些pragma,或者編譯器不支持OpenMp時,程序又可退化為通常的程序(一般為串行),代碼仍然可以正常運作,只是不能利用多線程來加速程序執行。OpenMP提供的這種對於並行描述的高層抽象降低了並行編程的難度和復雜度,這樣程序員可以把更多的精力投入到並行算法本身,而非其具體實現細節。對基於數據分集的多線程程序設計,OpenMP是一個很好的選擇。
OpenMP支持的語言包括C/C++、Fortran;而支持OpenMP的編譯器VS、gcc、clang等都行。可移植性也很好:Unix/Linux和Windows
OpenMP編程模型
內存共享模型:OpenMP是專為多處理器/核,共享內存機器所設計的。底層架構可以是UMA和NUMA。即(Uniform Memory Access和Non-Uniform Memory Access)

基於線程的並行性
- OpenMP僅通過線程來完成並行
- 一個線程的運行是可由操作系統調用的最小處理單
- 線程們存在於單個進程的資源中,沒有了這個進程,線程也不存在了
- 通常,線程數與機器的處理器/核數相匹配,然而,實際使用取決與應用程序
明確的並行
- OpenMP是一種顯式(非自動)編程模型,為程序員提供對並行化的完全控制
- 一方面,並行化可像執行串行程序和插入編譯指令那樣簡單
- 另一方面,像插入子程序來設置多級並行、鎖、甚至嵌套鎖一樣復雜
Fork-Join模型

- OpenMP就是采用Fork-Join模型
- 所有的OpenML程序都以一個單個進程——master thread開始,master threads按順序執行知道遇到第一個並行區域
- Fork:主線程創造一個並行線程組
- Join:當線程組完成並行區域的語句時,它們同步、終止,僅留下主線程
數據范圍
- 由於OpenMP時是共享內存模型,默認情況下,在共享區域的大部分數據是被共享的
- 並行區域中的所有線程可以同時訪問這個共享的數據
- 如果不需要默認的共享作用域,OpenMP為程序員提供一種“顯示”指定數據作用域的方法
嵌套並行
- API提供在其它並行區域放置並行區域
- 實際實現也可能不支持
動態線程
- API為運行環境提供動態的改變用於執行並行區域的線程數
- 實際實現也可能不支持
簡單使用
在VS2017中就可以使用,具體的:新建一個C/C++程序,項目--屬性--C/C++--語言--OpenMP支持,把OpenMP打開。然后編寫帶編譯指令的並行程序,注意一定要加上<omp.h>頭文件。
寫一個並行的Hello World
1 #include <omp.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 int main() 6 { 7 int nthreads, tid; 8 9 /* Fork a team of threads giving them their own copies of variables */ 10 #pragma omp parallel private(nthreads, tid) 11 { 12 13 /* Obtain thread number */ 14 tid = omp_get_thread_num(); 15 printf("Hello World from thread = %d\n", tid); 16 17 /* Only master thread does this */ 18 if (tid == 0) 19 { 20 nthreads = omp_get_num_threads(); 21 printf("Number of threads = %d\n", nthreads); 22 } 23 24 } /* All threads join master thread and disband */ 25 return 0; 26 }
運行結果如下:

注:我的電腦默認是4個線程,不同的電腦運行結果不同,就算是同一部電腦每次運行的結果也可能不同(4個線程並行執行,沒有確定的先后順序)
也可以直接使用gcc加上-fopenmp編譯,For example:
1 g++ test.cpp -o test -fopenmp 2 ./test
(不知道我的gcc不行,只能用g++,枯了)
補:直到原因了,gcc默認編譯鏈接不會鏈接C++標准庫,可以使用g++編譯鏈接(如上),也可以在gcc鏈接時顯示指定鏈接 -lstdc++
gcc test.cpp -o test -fopenmp -lstdc++
至於OpenMP詳細的編寫格式和意義可以看這篇博客。
參考資料:
1、https://blog.csdn.net/wyjkk/article/details/6612108
2、https://blog.csdn.net/HW140701/article/details/73716363
3、https://computing.llnl.gov/tutorials/openMP/#RunTimeLibrary
