2015-07-20 50 views
4

假設我有一個乘以2 std::vector的方法:的OpenMP:檢查嵌套parallesim

double multiply(std::vector<double> const& a, std::vector<double> const& b){ 
    double tmp(0); 
    /*here I could easily do a parallelization with*/ 
    /*#pragma omp parallel loop for*/ 
    for(unsigned int i=0;i<a.size();i++){ 
     tmp += a[i]*b[i]; 
    } 
    return tmp; 
} 

如果我在此功能設置的編譯宏,以multiply(...)通話將運行在所有線程 。

現在假設somewehere事我想做很多矢量乘法:

void many_multiplication(std::vector<double>* a, std::vector<double>* b, unsigned int N){ 
    /*here I could easily do a parallelization with*/ 
    /*#pragma omp parallel loop for*/ 
    for(unsigned int i=0;i<N;i++){ 
     for(unsigned int j=0;j<N;j++){ 
      multiply(a[i],b[j]); 
     } 
    } 
} 

我還可以做並行的方式相同。但是這會導致 不需要的嵌套並行。

如何檢查,如果multiply(..)是並行區域內調用, 那麼pragmamultiply(...)是「關閉」。如果它從非平行區域被稱爲 ,那麼它是「開啓」的。

+0

請注意您的示例代碼中的一個小錯字:您的「多個」函數會添加其輸入「vector」的值 – Novelocrat

+0

@Novelocrat ... oups :-) – PinkFloyd

回答

5

嵌套並行是禁用默認情況下,除非啓用特別是通過設置OMP_NESTEDtrue或致電omp_set_nested(1);OpenMP specification的§2.3.2)明確修改Avi Ginsburg建議的嵌套設置是一個壞主意。相反,你應該使用基於嵌套層次有條件的並行執行:

double multiply(std::vector<double> const& a, std::vector<double> const& b){ 
    double tmp(0); 
    int active_levels = omp_get_active_level(); 
    #pragma omp parallel for reduction(+:tmp) if(active_level < 1) 
    for(unsigned int i=0;i<a.size();i++){ 
     tmp += a[i]+b[i]; 
    } 
    return tmp; 
} 

omp_get_active_level()返回在調用時的瞬間包圍線程活動並行區域的數量。如果從並行區域外部調用或外部區域不活動,它將返回0。由於條款if(active_level < 1),平行區域只會被激活,即並行運行,如果沒有包含在活動區域​​中,則不管嵌套設置如何。

如果編譯器不支持的OpenMP 3.0或更高(例如,與任何版本的MS的Visual C/C++編譯器),然後omp_in_parallel()呼叫可以用來代替:

double multiply(std::vector<double> const& a, std::vector<double> const& b){ 
    double tmp(0); 
    int in_parallel = omp_in_parallel(); 
    #pragma omp parallel for reduction(+:tmp) if(in_parallel == 0) 
    for(unsigned int i=0;i<a.size();i++){ 
     tmp += a[i]+b[i]; 
    } 
    return tmp; 
} 

omp_in_parallel()返回非零值,如果在至少一個封閉平行區域是活動的,但不提供關於嵌套深度的信息,即不太靈活。

在任何情況下,編寫這樣的代碼都是不好的做法。您應該簡單地保留並行區域,並允許最終用戶選擇是否啓用嵌套並行。

+0

有趣。從哪個版本的OMP有'omp_get_active_level'存在?我通常使用VS(堅持2.0),我知道它不存在。 –

+0

在OpenMP 3.0中引入了對不同級別的並行性的單獨控制。使用3.0以前的編譯器時,可以使用'omp_in_parallel()'代替。 –

1

將編譯指示添加到兩個函數中。您可以使用omp_set_nested(int val)打開和關閉nested parallelism(零關閉,非零打開)。

所以,如果你想在你的一般程序嵌套並行,但關閉的many_multiplication功能,您將實現many_multiplication如下:

void many_multiplication(std::vector<double>* a, std::vector<double>* b, unsigned int N){ 
    omp_set_nested(0); 
    #pragma omp parallel loop for 
    for(unsigned int i=0;i<N;i++){ 
     for(unsigned int j=0;j<N;j++){ 
      multiply(a[i],b[j]); 
     } 
    } 
    omp_set_nested(1); 
} 
+0

thx。但如果我理解你的答案,並且如果我不想要嵌套並行性,那麼我可以將這個pragama添加到這兩個函數中,並且當在並行區域外部調用multiply時,它將並行化循環,但是當它在並行區域內調用時它不會並行化循環。 – PinkFloyd

+0

是的,但如果您從不想要嵌套並行性,則可以將環境變量OMP_NESTED定義爲true。 –

+0

對不起,我的意思是應該將OMP_NESTED定義爲false以禁用嵌套並行。如果未定義,則爲默認值。 –