OpenMP

--是一套支援跨平臺共享記憶體方式的多執行緒併發的程式設計API，使用C,C++和Fortran語言，可以在大多數的處理器體系和作業系統中執行，包括Solaris, AIX, HP-UX, GNU/Linux, Mac OS X, 和Microsoft Windows。包括一套編譯器指令、庫和一些能夠影響執行行為的環境變數。OpenMP採用可移植的、可擴充套件的模型，為程式設計師提供了一個簡單而靈活的開發平臺，從標準桌面電腦到超級計算機的並行應用程式介面。混合並行程式設計模型構建的應用程式可以同時使用OpenMP和MPI，或更透明地透過使用OpenMP擴充套件的非共享記憶體系統上執行的計算機叢集。OpenMP是由"OpenMP Architecture Review Board"牽頭提出的，並已被廣泛接受的，用於共享記憶體並行系統的多執行緒程式設計的一套指導性註釋，程式碼仍然可以正常運作，只是不能利用多執行緒來加速程式執行。介紹.OpenMP是一個跨平臺的多執行緒實現，主執行緒(順序的執行指令)生成一系列的子執行緒，並將任務劃分給這些子執行緒進行執行。這些子執行緒並行的執行，由執行時環境將執行緒分配給不同的處理器。要進行並行執行的程式碼片段需要進行相應的標記，用預編譯指令使得在程式碼片段被執行前生成執行緒，每個執行緒會分配一個"id"，可以透過函式(called codice_1)來獲得該值，該值是一個整數，主執行緒的id為0。在並行化的程式碼執行結束後，子執行緒"join"到主執行緒中，並繼續執行程式。預設情況下，各個執行緒獨立地執行並行區域的程式碼。可以使用"Work-sharing constructs"來劃分任務，使每個執行緒執行其分配部分的程式碼。透過這種方式，使用OpenMP可以實現任務並行和資料並行。執行時環境分配給每個處理器的執行緒數取決於使用方法、機器負載和其他因素。執行緒的數目可以透過環境變數或者程式碼中的函式來指定。在C/C++中，OpenMP的函式都宣告在標頭檔案"omp.h"中。歷史.OpenMP Architecture Review Board (ARB)於1997年10月釋出了OpenMP for Fortran 1.0。次年的10月，釋出了C/C++的標準。2000年，釋出了Fortran語言的2.0版本，並於2002年釋出了C/C++語言的2.0版本。2005年，包含Fortran和C/C++的2.5版本釋出了。在2008年5月釋出了3.0版。3.0中的新功能包括任務(tasks)和任務結構(task construct)的概念。這些新功能總結在OpenMP3.0規範的附錄F中。OpenMP規範的3.1版於2011年7月9日釋出。4.0版本在2013年7月釋出，它增加或改進以下功能：支援加速器，原子性，錯誤處理，執行緒關聯，任務擴充套件，減少使用者定義的SIMD支援和Fortran 2003的支援。特色.OpenMP提供的這種對於並行描述的高層抽象降低了並行程式設計的難度和複雜度，這樣程式設計師可以把更多的精力投入到並行演算法本身，而非其具體實現細節。對基於資料分集的多執行緒程式設計，OpenMP是一個很好的選擇。同時，使用OpenMP也提供了更強的靈活性，可以較容易的適應不同的並行系統配置。執行緒粒度和負載平衡等是傳統多執行緒程式設計中的難題，但在OpenMP中，OpenMP庫從程式設計師手中接管了部分這兩方面的工作。語法.directive.其中，directive共11個：clause.共計13個clause：OpenMP的庫函式.OpenMP定義了20多個庫函式：1.void omp_set_num_threads(int _Num_threads);在後續並行區域設定執行緒數，此呼叫隻影響呼叫執行緒所遇到的同一級或內部巢狀級別的後續並行區域.說明：此函式只能在序列程式碼部分呼叫.2.int omp_get_num_threads(void);返回當前執行緒數目.說明：如果在序列程式碼中呼叫此函式，返回值為1.3.int omp_get_max_threads(void);如果在程式中此處遇到未使用 num_threads() 子句指定的活動並行區域,則返回程式的最大可用執行緒數量.說明：可以在序列或並行區域呼叫，通常這個最大數量由omp_set_num_threads()或OMP_NUM_THREADS環境變數決定.4.int omp_get_thread_num(void);返回當前執行緒id.id從1開始順序編號,主執行緒id是0.5.int omp_get_num_procs(void);返回程式可用的處理器數.6.void omp_set_dynamic(int _Dynamic_threads);啟用或禁用可用執行緒數的動態調整.(預設情況下啟用動態調整.)此呼叫隻影響呼叫執行緒所遇到的同一級或內部巢狀級別的後續並行區域.如果 _Dynamic_threads 的值為非零值,啟用動態調整;否則,禁用動態調整.7.int omp_get_dynamic(void);確定在程式中此處是否啟用了動態執行緒調整.啟用了動態執行緒調整時返回非零值;否則,返回零值.8.int omp_in_parallel(void);確定執行緒是否在並行區域的動態範圍內執行.如果在活動並行區域的動態範圍內呼叫,則返回非零值;否則,返回零值.活動並行區域是指 IF 子句求值為 TRUE 的並行區域.9.void omp_set_nested(int _Nested);啟用或禁用巢狀並行操作.此呼叫隻影響呼叫執行緒所遇到的同一級或內部巢狀級別的後續並行區域._Nested 的值為非零值時啟用巢狀並行操作;否則,禁用巢狀並行操作.預設情況下,禁用巢狀並行操作.10.int omp_get_nested(void);確定在程式中此處是否啟用了巢狀並行操作.啟用巢狀並行操作時返回非零值;否則,返回零值.互斥鎖操作巢狀鎖操作功能11.void omp_init_lock(omp_lock_t * _Lock);12. void omp_init_nest_lock(omp_nest_lock_t * _Lock);初始化一個互斥鎖.13.void omp_destroy_lock(omp_lock_t * _Lock);14.void omp_destroy_nest_lock(omp_nest_lock_t * _Lock);結束一個互斥鎖的使用並釋放記憶體.15.void omp_set_lock(omp_lock_t * _Lock);16.void omp_set_nest_lock(omp_nest_lock_t * _Lock);獲得一個互斥鎖.17.void omp_unset_lock(omp_lock_t * _Lock);18.void omp_unset_nest_lock(omp_nest_lock_t * _Lock);釋放一個互斥鎖.19.int omp_test_lock(omp_lock_t * _Lock);20.int omp_test_nest_lock(omp_nest_lock_t * _Lock);試圖獲得一個.21.double omp_get_wtime(void);獲取wall clock time,返回一個double的數,表示從過去的某一時刻經歷的時間,一般用於成對出現,進行時間比較.此函式得到的時間是相對於執行緒的,也就是每一個執行緒都有自己的時間.22.double omp_get_wtick(void);得到clock ticks的秒數.例子.在 "omp parallel" 段內的程式程式碼由多執行緒來執行：int main(int argc, char* argv[])#pragma omp parallelprintf("Hello, world.\n");return 1;環境變數.OpenMP可以使用[[環境變數]] "OMP_NUM_THREADS"以控制執行執行緒的數量。優點和缺點.優點缺點爭議.作為高層抽象，OpenMP並不適合需要複雜的執行緒間同步和互斥的場合。 OpenMP的另一個缺點是不能在非共享記憶體系統上使用。在這樣的系統上，[[MPI]]使用較多。編譯器支援.主流C/C++編譯器，如gcc與visual C++，都內在支援OpenMP。一般都必須在程式中codice_2gcc編譯時需使用編譯選項-fopenmp。但是，如果編譯為目標檔案與連結生成可執行檔案是分開為兩步操作，那麼連結時需要給出附加庫gomp，否則會在連結時報錯“undefined reference to `omp_get_thread_num'"。Visual C++需要在IDE的編譯選項-&gt;語言-&gt;支援OpenMP。這實際上使用了編譯選項/openmp[[Category:C語言家族]][[Category:併發計算]][[Category:應用程式介面]]