2015-09-15 70 views
2

我想重構基於OpenMP的程序,並遇到一個可怕的可伸縮性問題。以下(顯然不是很有意義)的OpenMP程序似乎重現了這個問題。當然,微小的示例代碼可以重寫爲嵌套for循環,並且可以實現幾乎完美的可擴展性。但是,我正在處理的原始程序不允許這樣做。OpenMP並行的內部做 - 而

因此,我正在尋找一個修復程序,保持do-while結構。根據我的理解,OpenMP應該足夠聰明,以保持迭代之間的線程活躍,並且我期望具有良好的可伸縮性。爲什麼不是這種情況?

int main() { 
    const int N = 6000; 
    const int MAX_ITER = 2000000; 
    double max = DBL_MIN; 

    int iter = 0; 
    do { 
     #pragma omp parallel for reduction(max:max) schedule(static) 
     for(int i = 1; i < N; ++i) { 
      max = MAX(max, 3.3*i); 
     } 
    ++iter; 
    } while(iter < MAX_ITER); 

    printf("max=%f\n", max); 
} 

我用Cray compiler 8.3.4測量了以下運行時間。

OMP_NUM_THREADS=1 : 0m21.535s 
OMP_NUM_THREADS=2 : 0m12.191s 
OMP_NUM_THREADS=4 : 0m9.610s 
OMP_NUM_THREADS=8 : 0m9.767s 
OMP_NUM_THREADS=16: 0m13.571s 

這似乎與this question相似。提前致謝。幫助表示讚賞! :)

+0

你的物理機器上有多少個線程/內核?另外,如果你在'for'循環中只做很少的工作,你可能無法獲得良好的可伸縮性。 – NoseKnowsAll

+0

我有32個內核分在2個CPU之間。每個核心都有2個超線程線程。 CPU是Intel Xeon E5-2698v3。 – aka

回答

1

你可以去這樣的事情:

#include <stdio.h> 
#include <float.h> 
#include <omp.h> 
#define MAX(a, b) ((a)>(b))?(a):(b) 

int main() { 
    const int N = 6000; 
    const int MAX_ITER = 2000000; 
    double max = DBL_MIN; 

    #pragma omp parallel reduction(max : max) 
    { 
     int iter = 0; 
     int nbth = omp_get_num_threads(); 
     int tid = omp_get_thread_num(); 
     int myMaxIter = MAX_ITER/nbth; 
     if (tid < MAX_ITER % nbth) myMaxIter++; 
     int chunk = N/nbth; 
     do { 
      #pragma omp for schedule(dynamic,chunk) nowait 
      for(int i = 1; i < N; ++i) { 
       max = MAX(max, 3.3*i); 
      } 
      ++iter; 
     } while(iter < myMaxIter); 
    } 
    printf("max=%f\n", max); 
} 

我敢肯定的可擴展性應該出了名的提高。

注意:由於我意識到外循環(do-while)的迭代次數對於不同的線程有潛在的不同,所以我不得不重複這幾次,所以至關重要的是omp for循環的調度不是靜態的,否則,在最後一次迭代中存在死鎖的可能性。 我做了一些測試,我認爲建議的解決方案既安全又有效。

+0

謝謝你的建議。我想我找到了一個基於它的解決方案。有沒有解釋爲什麼我的原始代碼表現糟糕?是否在我的版本中,只要輸入「parallel」就會創建多個線程?爲什麼線程不在「並行」區域之間? – aka

+0

這就是OpenMP的工作方式......這是它的fork-join模型的基礎。出於好奇,你能發佈你的解決方案嗎? – Gilles

+0

謝謝。然後我誤解了一些東西。代碼仍在工作中。這是一個混合OpenMP + MPI項目。完成工作後,可以發佈完整的代碼。 – aka