OpenMP中的任務排程

2021-04-13 14:29:03 字數 4207 閱讀 8213

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中的任務排程 openmp中,任務排程主要用於並行的for迴圈中,當迴圈中每次迭代的計算量不相等時,如果簡單地給各個執行緒分配相同次數的迭代的話,會造成各個執行緒計算負載不均衡,這會使得有些執行緒先執行完,有些後執行完,造成某些cpu核空閒,影響程式效能。例如以下 int i,j int...

OpenMP中的任務排程

openmp中的任務排程 openmp中,任務排程主要用於並行的for迴圈中,當迴圈中每次迭代的計算量不相等時,如果簡單地給各個執行緒分配相同次數的迭代的話,會造成各個執行緒計算負載不均衡,這會使得有些執行緒先執行完,有些後執行完,造成某些cpu核空閒,影響程式效能。例如以下 int i,j int...

OpenMP中的任務排程

openmp中的任務排程 openmp中,任務排程主要用於並行的for迴圈中,當迴圈中每次迭代的計算量不相等時,如果簡單地給各個執行緒分配相同次數的迭代的話,會造成各個執行緒計算負載不均衡,這會使得有些執行緒先執行完,有些後執行完,造成某些cpu核空閒,影響程式效能。例如以下 int i,j int...