本文原發表於:http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!1280.entry
之前對於多執行緒和 OpenMP 的平行化已經做了些簡單的介紹,有興趣的可以回頭參考《簡易的程式平行化方法-OpenMP(一) 》。而由於 Heresy 最近看了些資料,也做了些測試,所以主要可能想來講最近學的一些語法吧~
首先,在 Heresy 的認知裡,一般會用到 OpenMP 的部分分為三類:
而 function 的部份是獨立呼叫的,其實在一般的情況下,似乎不大會用到。而 directive 和 clause 的用法,大致上應該是:
#pragma omp directive [clause]
的形式。像之前 #pragma omp parallel for,實際上 parallel 和 for 都是 directive;所以語法實際上可以拆開成 #pragma omp parallel 和 #pragma omp for 兩行。也就是
#pragma omp parallel for for( int i = 0; i < 10; i ) Test( i );
實際上是
#pragma omp parallel { #pragma omp for for( int i = 0; i < 10; i ) Test( i ); }
所形成的。
而 OpenMP 的 directive 列表如下:
atomic | 記憶體位址將會自動更新。這個指令的目的在於避免變數備同時修改而造成計算結果錯誤。 Specifies that a memory location that will be updated atomically. |
barrier | 等待,直到所有的執行緒都執行到 barrier。用來同步化。 Synchronizes all threads in a team; all threads pause at the barrier, until all threads execute the barrier. |
critical | 強制接下來的程式一次只會被一個執行緒執行。 Specifies that code is only executed on one thread at a time. |
flush | Specifies that all threads have the same view of memory for all shared objects. |
for | 用在 for 迴圈之前,會將迴圈平行化處理。(註:迴圈的 index 只能是 int) Causes the work done in a for loop inside a parallel region to be divided among threads. |
master | 指定由主執行緒來執行接下來的程式。 Specifies that only the master thread should execute a section of the program. |
ordered | 指定接下來被程式,在被平行化的 for 迴圈將依序的執行。 Specifies that code under a parallelized for loop should be executed like a sequential loop. |
parallel | 代表接下來的程式將被平行化。 Defines a parallel region, which is code that will be executed by multiple threads in parallel. |
sections | 將接下來的 section 平行化處理。 Identifies code sections to be divided among all threads. |
single | 之後的程式將只會在一個執行緒執行,不會被平行化。 Lets you specify that a section of code should be executed on a single thread, not necessarily the master thread. |
threadprivate | Specifies that a variable is private to a thread. |
雖然只有 11 個,但是已經有點頭大了;有的 Heresy 還是不能確定它的用途、效果。
其中,要拿來平行化,是使用 parallel、sections、for 這三項;而要指定使用單一執行緒,則是特過 master、single、crigical 這三項。barrier 則是拿來控制執行緒同步用的;ordered 是用來設定平行化的執行順序。atomic、flush、threadprivate 則應該都是用來控制變數的。
而 clause 的部份,則有下列 13 個:
copyin | 讓 threadprivate 的變數的值和主執行緒的值相同。 Allows threads to access the master thread’s value, for a threadprivate variable. |
copyprivate | 將不同執行緒中的變數共用。 Specifies that one or more variables should be shared among all threads. |
default | 設定平行化時對變數處理方式的預設值。 Specifies the behavior of unscoped variables in a parallel region. |
firstprivate | 讓每個執行緒中,都有一份變數的複本,以免互相干擾;而起始值則會是開始平行化之前的變數值。 Specifies that each thread should have its own instance of a variable, and that the variable should be initialized with the value of the variable, because it exists before the parallel construct. |
if | 判斷條件,可以用來決定是否要平行化。 Specifies whether a loop should be executed in parallel or in serial. |
lastprivate | 讓每個執行緒中,都有一份變數的複本,以免互相干擾;而在所有平行化的執行緒都結束後,會把最後的值,寫回主執行緒。 Specifies that the enclosing context’s version of the variable is set equal to the private version of whichever thread executes the final iteration (for-loop construct) or last section (#pragma sections). |
nowait | 忽略 barrier(等待)。 Overrides the barrier implicit in a directive. |
num_threads | 設定平行化時執行緒的數量。 Sets the number of threads in a thread team. |
ordered | 使用於 for,可以在將迴圈平行化的時候,將程式中有標記 directive ordered 的部份依序執行。 Required on a parallel for (OpenMP) statement if an ordered (OpenMP Directives) directive is to be used in the loop. |
private | 讓每個執行緒中,都有一份變數的複本,以免互相干擾。 Specifies that each thread should have its own instance of a variable. |
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. |
schedule | 設定 for 迴圈的平行化方法;有 dynamic、guided、runtime、static 四種方法。 Applies to the for (OpenMP) directive. |
shared | 將變數設定為各執行緒共用(應該算是相對於 private 的)。 Specifies that one or more variables should be shared among all threads. |
而在 clause 的中,copyin、copyprivate、default、shared、private、firstprivate、lastprivate、reduction 這 8 項,都是用來控制變數在平行化時的處理方法的。ordered 和 schedule 是控制平行化時的執行順序分配方法;num_threads、if 則比較像是控制執行緒的設定。
而在 Function 的部份,MSDN 列了二十來個 function;不過就 Heresy 感覺是用到機會似乎不高,所以在這邊就不列出來了。(也懶的研究了 :p)
雖然一般可能用不到,但是在測試的時候,為了驗正執行的順序、多執行緒的關係,有時候必須要知道線在是由哪個執行緒在跑的這時候,可以透過 omp_get_thread_num() 這個函式,來取得目前執行緒的編號。
註:
- 雖然 VisualStudio 2005 Express 也有 OpenMP 的選項,但是實際上並沒有附上 OpenMP 的函式庫,所以理論上是不能用的;不過如果能找到 Standard 或 Professional 版的檔案放進去,也是可以運作的!
- 神奇的是…原則上如果沒有用到 OpenMP 的 Function,而只是用 directive 和 clause 的話,應該是可以不用 #include <omp.h> 才對;但是在 Express 中,不加入 #include <omp.h> 可以正確的編譯、執行,而 Professional 版卻只能正確的編譯,而無法正確的執行(dll 起始錯誤)。
參考資料:
- OpenMP并行程序设计(一):http://blog.csdn.net/drzhouweiming/archive/2006/08/28/1131537.aspx
OpenMP并行程序设计(二):http://blog.csdn.net/drzhouweiming/archive/2006/09/04/1175848.aspx - MSDN 的 OpenMP:http://msdn2.microsoft.com/en-us/library/tt15eb9t.aspx
目錄: