What's OpenMP
The OpenMP API supports multi-platform shared-memory parallel programming in C/C++ and Fortran. The OpenMP API defines a portable, scalable model with a simple and flexible interface for developing parallel applications on platforms from the desktop to the supercomputer.
語法
#pragma omp <directive> [clause[[,] clause] ...]
directive
1.? atomic: 內存位置將會原子更新,只對下一行有效。
2.? barrier: 線程在此等待,直到所有的線程都運行到此barrier。用來同步所有線程,只對下一行有效。
3.? critical: 其后的代碼塊為臨界區,任意時刻只能被一個線程運行,只對下一行有效。
4.? flush: 所有線程對所有共享對象具有相同的內存視圖(view of memory)
5.? for: 用在for循環之前,把for循環并行化由多個線程執行。循環變量只能是整型
6.? master: 指定由主線程來運行接下來的程序。
7.? ordered: 指定在接下來的代碼塊中,被并行化的 for循環將依序運行(sequential loop)
8.? parallel: 代表接下來的代碼塊將被多個線程并行各執行一遍。
9.? sections: 將接下來的代碼塊包含將被并行執行的section塊。
10. single:之后的程序將只會在一個線程(未必是主線程)中被執行,不會被并行執行。
11. threadprivate 指定一個變量是線程局部存儲(thread local storage)
clause
1.? copyin: 讓threadprivate的變量的值和主線程的值相同。
2.? copyprivate: 不同線程中的變量在所有線程中共享。
3.? default: Specifies the behavior of unscoped variables in a parallel region.
4.? firstprivate: 對于線程局部存儲的變量,其初值是進入并行區之前的值。
5.? if: 判斷條件,可用來決定是否要并行化。
6.? lastprivate: 在一個循環并行執行結束后,指定變量的值為循環體在順序最后一次執行時獲取的值,或者#pragma sections在中,按文本順序最后一個section中執行獲取的值。
7.? nowait: 忽略barrier的同步等待。
8.? num_threads: 設置線程數量的數量。默認值為當前計算機硬件支持的最大并發數。一般就是CPU的內核數目。超線程被操作系統視為獨立的CPU內核。
9.? ordered: 使用于 for,可以在將循環并行化的時候,將程序中有標記 directive ordered 的部分依序運行。
10. private: 指定變量為線程局部存儲。
11. reduction: Specifies that one or more variables that are private to each thread are the subject of a reduction operation at the end of the parallel region.
12. schedule: 設置for循環的并行化方法;有 dynamic、guided、runtime、static 四種方法。
? ? 1)schedule(static, chunk_size) 把chunk_size數目的循環體的執行,靜態依序指定給各線程。
? ? 2)schedule(dynamic, chunk_size) 把循環體的執行按照chunk_size(缺省值為1)分為若干組(即chunk),每個等待的線程獲得當前一組去執行,執行完后重新等待分配新的組。
? ? 3)schedule(guided, chunk_size) 把循環體的執行分組,分配給等待執行的線程。最初的組中的循環體執行數目較大,然后逐漸按指數方式下降到chunk_size。
? ? 4)schedule(runtime) 循環的并行化方式不在編譯時靜態確定,而是推遲到程序執行時動態地根據環境變量OMP_SCHEDULE 來決定要使用的方法。
13. shared: 指定變量為所有線程共享。
常用directive
parallel:
#pragma omp parallel [clause[[,]clause]...]
{
}
clause type:
if([parallel :]scalar-expression)
num_threads(integer-expression)
default(shared | none)
private(list)
firstprivate(list)
shared(list)
copyin(list)
reduction([reduction-modifier ,] reduction-identifier : list)
proc_bind(master | close | spread)
allocate([allocator :] list)
for :
#pragma omp for?[clause[[,]clause]...]
{
}
clause type:
private(list)
firstprivate(list)
lastprivate([ lastprivate-modifier:] list)
linear(list[ : linear-step])
reduction([ reduction-modifier,]reduction-identifier : list)
schedule([modifier[, modifier]:]kind[,chunk_size])? ? // static/dynamic/guided/auto/runtime
collapse(n)? ? ? ? //for嵌套層數
ordered[(n)]allocate([allocator :]list)
order(concurrent)
約束條件:
1. for循環中比較操作符必須是<, <=, >, >=。例如for (int i = 0; i != 10; ++i){}會編譯不通過
2.?循環必須是單入口、單出口,也就是說循環內部不允許能夠達到循環以外的跳轉語句,exit除外。異常的處理也必須在循環體內處理。例如:若循環體內的break或goto會跳轉到循環體外,那么會編譯不通過
常用庫函數
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);
試圖獲得一個(嵌套)互斥鎖,并在成功時放回真(true),失敗是返回假(false).
21.double omp_get_wtime(void);
獲取wall clock time,返回一個double的數,表示從過去的某一時刻經歷的時間,一般用于成對出現,進行時間比較. 此函數得到的時間是相對于線程的,也就是每一個線程都有自己的時間.
22.double omp_get_wtick(void);
得到clock ticks的秒數.
編譯
g++ xxx -fopenmp
引用
https://zh.wikipedia.org/wiki/OpenMP
https://www.cnblogs.com/liangliangh/p/3565234.html