OpenMP 中的線程任務調度


OpenMP中任務調度主要針對並行的for循環,當循環中每次迭代的計算量不相等時,如果簡單地給各個線程分配相同次數的迭代,則可能會造成各個線程計算負載的不平衡,影響程序的整體性能。

如下面的代碼中,如果每個線程執行的任務數量平均分配,有的線程會結束早,有的線程結束晚:

 1 #include<stdio.h>
 2 #include<omp.h>
 3 
 4 int main(){
 5     int a[100][100] = {0};
 6 #pragma omp parallel for
 7     for (int i =0; i < 100; i++){
 8         for(int j = i; j < 100; j++ )
 9             a[i][j] = ((i%7)*(j%13)%23);
10     }
11     return 0;
12 }

 

為此,OpenMP提供了schedule子句來實現任務的調度。

schedule子句:

  schedule(type[, size]),

  參數type是指調度的類型,可以取值為static,dynamic,guided,runtime四種值。其中runtime允許在運行時確定調度類型,因此實際調度策略只有前面三種。

  參數size表示每次調度的迭代數量,必須是整數。該參數是可選的。當type的值是runtime時,不能夠使用該參數。

1.靜態調度static

  大部分編譯器在沒有使用schedule子句的時候,默認是static調度。static在編譯的時候就已經確定了,那些循環由哪些線程執行。

  當不使用size 時,將給每個線程分配┌N/t┐個迭代。當使用size時,將每次給線程分配size次迭代。

  如下面代碼:

 1 #include<stdio.h>
 2 #include<omp.h>
 3 int main(){
 4     int a[100][100] = {0};
 5 #pragma omp parallel for schedule(static)
 6 //#pragma omp parallel for schedule(static,5)
 7     for (int i =0; i < 100; i++){
 8         printf("id=%d i=%d\n",omp_get_thread_num(),i);
 9     }
10     return 0;
11 }
View Code

  在四核機器上執行:

  (1)當不使用參數時,100/4=25,0-24由1號線程執行;25-49由2號線程執行;50-74由3號線程執行;75-99由4號線程執行

  (1)當不使用參數時,x(x=0,1,2,3)線程執行((n/5)%4)任務。其中n=0-99。

2.動態調度dynamic

  動態調度依賴於運行時的狀態動態確定線程所執行的迭代,也就是線程執行完已經分配的任務后,會去領取還有的任務。由於線程啟動和執行完的時間不確定,所以迭代被分配到哪個線程是無法事先知道的。

  當不使用size 時,是將迭代逐個地分配到各個線程。當使用size 時,逐個分配size個迭代給各個線程。

  如下面代碼:

 1 #include<stdio.h>
 2 #include<omp.h>
 3 int main(){
 4     int a[100][100] = {0};
 5 #pragma omp parallel for schedule(dynamic)
 6 //#pragma omp parallel for schedule(dynamic,5)
 7     for (int i =0; i < 100; i++){
 8         printf("id=%d i=%d\n",omp_get_thread_num(),i);
 9     }
10     return 0;
11 }
View Code

3.啟發式調度guided

   采用啟發式調度方法進行調度,每次分配給線程迭代次數不同,開始比較大,以后逐漸減小。

  size表示每次分配的迭代次數的最小值,由於每次分配的迭代次數會逐漸減少,少到size時,將不再減少。如果不知道size的大小,那么默認size為1,即一直減少到1。具體采用哪一種啟發式算法,需要參考具體的編譯器和相關手冊的信息。

 

三種運行方式總結:

靜態調度static:每次哪些循環由那個線程執行時固定的,編譯調試。由於每個線程的任務是固定的,但是可能有的循環任務執行快,有的慢,不能達到最優。

動態調度dynamic:根據線程的執行快慢,已經完成任務的線程會自動請求新的任務或者任務塊,每次領取的任務塊是固定的。

啟發式調度guided:每個任務分配的任務是先大后小,指數下降。當有大量任務需要循環時,剛開始為線程分配大量任務,最后任務不多時,給每個線程少量任務,可以達到線程任務均衡。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM