openmp中的任務排程
openmp中,任務排程主要用於並行的for迴圈中,當迴圈中每次迭代的計算量不相等時,如果簡單地給各個執行緒分配相同次數的迭代的話,會造成各個執行緒計算負載不均衡,這會使得有些執行緒先執行完,有些後執行完,造成某些cpu核空閒,影響程式效能。例如以下**:
int i, j;
int a[100][100] = ;
for ( i =0; i < 100; i++)
} 如果將最外層迴圈並行化的話,比如使用4個執行緒,如果給每個執行緒平均分配25次迴圈迭代計算的話,顯然i=0和i=99的計算量相差了100倍,那麼各個執行緒間可能出現較大的負載不平衡情況。為了解決這些問題,openmp中提供了幾種對for迴圈並行化的任務排程方案。
在openmp中,對for迴圈並行化的任務排程使用schedule子句來實現,下面介紹schedule字句的用法。
1.1.1schedule子句用法
schedule子句的使用格式為:
schedule(type[,size])
schedule有兩個引數:type和size,size引數是可選的。 1.
type引數
表示排程型別,有四種排程型別如下:
·dynamic
·guided
·runtime
·static
這四種排程型別實際上只有static、dynamic、guided三種排程方式,runtime實際上是根據環境變數來選擇前三種中的某中型別。
run-sched-var 2.
size
引數 (可選)
size
引數表示迴圈迭代次數,
size
引數必須是整數。static、dynamic、guided三種排程方式都可以使用size引數,也可以不使用size引數。
當type
引數型別為
runtime
時,size
引數是非法的(不需要使用,如果使用的話編譯器會報錯)。
1.1.2靜態排程(static)
靜態排程時可以不使用size引數,也可以使用size引數。
3.不使用size引數
不使用size引數時,分配給每個執行緒的是n/t次連續的迭代,不使用size引數的用法如下:
schedule(static)
例如以下**:
#pragma omp parallel for schedule(static)
for(i = 0; i < 10; i++ )
上面**執行時列印的結果如下:
i=0, thread_id=0
i=1, thread_id=0
i=2, thread_id=0
i=3, thread_id=0
i=4, thread_id=0
i=5, thread_id=1
i=6, thread_id=1
i=7, thread_id=1
i=8, thread_id=1
i=9, thread_id=1
可以看出執行緒0得到了0~4次連續迭代,執行緒1得到5~9次連續迭代。注意由於多執行緒執行時序的隨機性,每次執行時列印的結果順序可能存在差別,後面的例子也一樣。
4.使用size引數
使用size引數時,分配給每個執行緒的size次連續的迭代計算,用法如下:
schedule(static, size)
例如以下**:
#pragma omp parallel for schedule(static, 2)
for(i = 0; i < 10; i++ )
執行時會列印以下結果:
i=0, thread_id=0
i=1, thread_id=0
i=4, thread_id=0
i=5, thread_id=0
i=8, thread_id=0
i=9, thread_id=0
i=2, thread_id=1
i=3, thread_id=1
i=6, thread_id=1
i=7, thread_id=1
從列印結果可以看出,0、1次迭代分配給執行緒0,2、3次迭代分配給執行緒1,4、5次迭代分配給執行緒0,6、7次迭代分配給執行緒1,…。每個執行緒依次分配到2次連續的迭代計算。
1.1.3動態排程(dynamic)
動態排程是動態地將迭代分配到各個執行緒,動態排程可以使用size引數也可以不使用size引數,不使用size引數時是將迭代逐個地分配到各個執行緒,使用size引數時,每次分配給執行緒的迭代次數為指定的size次。
下面為使用動態排程不帶size引數的例子:
#pragma omp parallel for schedule(dynamic)
for(i = 0; i < 10; i++ )
列印結果如下:
i=0, thread_id=0
i=1, thread_id=1
i=2, thread_id=0
i=3, thread_id=1
i=5, thread_id=1
i=6, thread_id=1
i=7, thread_id=1
i=8, thread_id=1
i=4, thread_id=0
i=9, thread_id=1
下面為動態排程使用size引數的例子:
#pragma omp parallel for schedule(dynamic, 2)
for(i = 0; i < 10; i++ )
列印結果如下:
i=0, thread_id=0
i=1, thread_id=0
i=4, thread_id=0
i=2, thread_id=1
i=5, thread_id=0
i=3, thread_id=1
i=6, thread_id=0
i=8, thread_id=1
i=7, thread_id=0
i=9, thread_id=1
從列印結果可以看出第0、1,4、5,6、7次迭代被分配給了執行緒0,第2、3,8、9次迭代則分配給了執行緒1,每次分配的迭代次數為2。
1.1.4guided排程(guided)
guided排程是一種採用指導性的啟發式自排程方法。開始時每個執行緒會分配到較大的迭代塊,之後分配到的迭代塊會逐漸遞減。迭代塊的大小會按指數級下降到指定的size大小,如果沒有指定size引數,那麼迭代塊大小最小會降到1。
例如以下**:
#pragma omp parallel for schedule(guided,2)
for(i = 0; i < 10; i++ )
列印結果如下:
i=0, thread_id=0
i=1, thread_id=0
i=2, thread_id=0
i=3, thread_id=0
i=4, thread_id=0
i=8, thread_id=0
i=9, thread_id=0
i=5, thread_id=1
i=6, thread_id=1
i=7, thread_id=1
第0、1、2、3、4次迭代被分配給執行緒0,第5、6、7次迭代被分配給執行緒1,第8、9次迭代被分配給執行緒0,分配的迭代次數呈遞減趨勢,最後一次遞減到2次。
1.1.5runtime排程(rumtime)
runtime排程並不是和前面三種排程方式似的真實排程方式,它是在執行時根據環境變數omp_schedule來確定排程型別,最終使用的排程型別仍然是上述三種排程方式中的某種。
例如在unix系統中,可以使用setenv命令來設定omp_schedule環境變數:
setenv omp_schedule 「dynamic, 2」
上述命令設定排程型別為動態排程,動態排程的迭代次數為2。
在windows環境中,可以在」系統屬性|高階|環境變數」對話方塊中進行設定環境變數。
OpenMP中的任務排程
openmp中,任務排程主要用於並行的for迴圈中,當迴圈中每次迭代的計算量不相等時,如果簡單地給各個執行緒分配相同次數的迭代的話,會造成各個執行緒計算負載不均衡,這會使得有些執行緒先執行完,有些後執行完,造成某些cpu核空閒,影響程式效能。例如以下 int i,j int a 100 100 fo...
OpenMP中的任務排程
openmp中的任務排程 openmp中,任務排程主要用於並行的for迴圈中,當迴圈中每次迭代的計算量不相等時,如果簡單地給各個執行緒分配相同次數的迭代的話,會造成各個執行緒計算負載不均衡,這會使得有些執行緒先執行完,有些後執行完,造成某些cpu核空閒,影響程式效能。例如以下 int i,j int...
OpenMP中的任務排程
openmp中的任務排程 openmp中,任務排程主要用於並行的for迴圈中,當迴圈中每次迭代的計算量不相等時,如果簡單地給各個執行緒分配相同次數的迭代的話,會造成各個執行緒計算負載不均衡,這會使得有些執行緒先執行完,有些後執行完,造成某些cpu核空閒,影響程式效能。例如以下 int i,j int...