2016-01-09 64 views
3

假設我有以下一個在內部使用#pragma omp parallel的功能。如何將OpenMP線程拆分爲一個循環的子工作流

void do_heavy_work(double * input_array); 

我現在想do_heavy_work許多input_arrays這樣的:

void do_many_heavy_work(double ** input_arrays, int num_arrays) 
{ 
    for (int i = 0; i < num_arrays; ++i) 
    { 
     do_heavy_work(input_arrays[i]); 
    } 
} 

比方說,我有N硬件線程。上面的實現會導致調用do_heavy_work以串行方式發生,每個使用內部的所有N線程執行任何想要的並行任務。

現在假定當num_arrays > 1與其在內部平行於do_heavy_work時實際上在此外部循環上並行效率更高。我現在有以下選擇。

  • #pragma omp parallel for放在外環上並設置OMP_NESTED=1。但是,通過設置OMP_NUM_THREADS=N,我將最終產生大量的線程(N*num_arrays)。
  • 同上,但關閉嵌套並行。當num_arrays < N時,這會浪費可用核心。

理想我想的OpenMP它的OMP_NUM_THREADS線程隊分成num_arrays工作小組,然後,如果給出了一些每個do_heavy_work可以跟帖超過其分配的工作小組。

實現此目的的最簡單方法是什麼?

(爲了討論的目的,讓我們假設num_arrays不一定事先知道,而且也是我無法改變的代碼do_heavy_work本身。該代碼將可以在多臺機器的工作,所以N應該是自由定的。)

回答

3

OMP_NUM_THREADS可以設置爲一個列表,從而指定每個嵌套級別的線程數。例如。 OMP_NUM_THREADS=10,4將告訴OpenMP運行時使用10個線程執行外部並行區域,每個嵌套區域將使用4個線程執行,最多可同時運行40個線程。

或者,你可以讓你的程序與適應類似這樣的代碼:

void do_many_heavy_work(double ** input_arrays, int num_arrays) 
{ 
    #pragma omp parallel num_threads(num_arrays) 
    { 
     int nested_team_size = omp_get_max_threads()/num_arrays; 
     omp_set_num_threads(nested_team_size); 

     #pragma omp for 
     for (int i = 0; i < num_arrays; ++i) 
     { 
      do_heavy_work(input_arrays[i]); 
     } 
    } 
} 

此代碼不會使用所有可用線程如果OMP_NUM_THREADS值不是整除num_arrays。如果每個嵌套區域的線程數量不同(這可能會導致某些數組的處理速度比其他數據快),請提出如何分配線程的想法,並相應地在每個線程中設置nested_team_size。從並行區域內調用omp_set_num_threads()僅影響由調用線程啓動的嵌套區域,因此您可以擁有不同的嵌套團隊大小。

+0

謝謝!我沒有意識到omp_set_num_threads()僅影響當前線程的上下文。 – Saran