簡易的程式平行化-OpenMP(二)語法說明

| | 0 Comments| 10:20
Categories:

本文原發表於:http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!1280.entry


之前對於多執行緒和 OpenMP 的平行化已經做了些簡單的介紹,有興趣的可以回頭參考《簡易的程式平行化方法-OpenMP(一) 》。而由於 Heresy 最近看了些資料,也做了些測試,所以主要可能想來講最近學的一些語法吧~

首先,在 Heresy 的認知裡,一般會用到 OpenMP 的部分分為三類:

  1. Directives
  2. Clauses
  3. Functions

而 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 還是不能確定它的用途、效果。

其中,要拿來平行化,是使用 parallelsectionsfor 這三項;而要指定使用單一執行緒,則是特過 mastersinglecrigical 這三項。barrier 則是拿來控制執行緒同步用的;ordered 是用來設定平行化的執行順序。atomicflushthreadprivate 則應該都是用來控制變數的。


而 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 的中,copyincopyprivatedefaultsharedprivatefirstprivatelastprivatereduction 這 8 項,都是用來控制變數在平行化時的處理方法的。orderedschedule 是控制平行化時的執行順序分配方法;num_threadsif 則比較像是控制執行緒的設定。


而在 Function 的部份,MSDN 列了二十來個 function;不過就 Heresy 感覺是用到機會似乎不高,所以在這邊就不列出來了。(也懶的研究了 :p)

雖然一般可能用不到,但是在測試的時候,為了驗正執行的順序、多執行緒的關係,有時候必須要知道線在是由哪個執行緒在跑的這時候,可以透過 omp_get_thread_num() 這個函式,來取得目前執行緒的編號。


註:

  1. 雖然 VisualStudio 2005 Express 也有 OpenMP 的選項,但是實際上並沒有附上 OpenMP 的函式庫,所以理論上是不能用的;不過如果能找到 Standard 或 Professional 版的檔案放進去,也是可以運作的!
  2. 神奇的是…原則上如果沒有用到 OpenMP 的 Function,而只是用 directive 和 clause 的話,應該是可以不用 #include <omp.h> 才對;但是在 Express 中,不加入 #include <omp.h> 可以正確的編譯、執行,而 Professional 版卻只能正確的編譯,而無法正確的執行(dll 起始錯誤)。

參考資料:

  1. OpenMP并行程序设计(一):http://blog.csdn.net/drzhouweiming/archive/2006/08/28/1131537.aspx
    OpenMP并行程序设计(二):http://blog.csdn.net/drzhouweiming/archive/2006/09/04/1175848.aspx
  2. MSDN 的 OpenMP:http://msdn2.microsoft.com/en-us/library/tt15eb9t.aspx

目錄:

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *