2012-11-27 68 views
0

我遇到的問題了解OpenMP如何與嵌套循環一起工作。請幫忙!OpenMP嵌套循環,代碼在幹什麼?

我得到了下面的代碼以並行方式運行:

#pragma omp parallel private(i) 
{ 
for(i=0; i<n; i++) 
{ 
    #pragma omp for 
    for(j=0; j<n; j++) 
    { 
     if(asubsref(seed,j) > 0) 
      asubsref(bin,j) = asubsref(bin,j) + 1; 
    } 
    #pragma omp for 
    for(j=0; j<n; j++) 
     asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i); 
} 
} 

不過,我不太清楚這個代碼是如何工作(我只是靠運氣得到它)。這是我認爲它正在做...

因此for(i=0; i<n; i++)被拆分成不同的線程並行運行。因爲i被宣佈爲private,所以循環的每個實例都是「沙箱」;也就是說,j的所有更改都保留在該線程中(至少在所有線程完成之前?)。我很困惑,因爲沒有聲明#pragma omp for導致代碼打破...我不知道這是爲什麼。

如果有人能夠引導我完成這段代碼的工作,我會非常感激!謝謝!

+0

http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=%2Fcom.ibm.vacpp7a.doc%2Fcompiler%2Fref%2Fruompfor.htm – imreal

回答

2

這是人們爲了減少多次進入的開銷而存在於並行區域之內的典型做法。從你的問題的代碼比較下面的等效代碼:

for (i=0; i<n; i++) 
{ 
    #pragma omp parallel for 
    for (j=0; j<n; j++) 
    { 
     if (asubsref(seed,j) > 0) 
      asubsref(bin,j) = asubsref(bin,j) + 1; 
    } 
    #pragma omp parallel for 
    for (j=0; j<n; j++) 
     asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i); 
} 

它運行在in次外循環。在外部循環的每次迭代中,它在j上運行兩個並行循環,在這些線程之間分割迭代。這裏的問題是你內部有兩個平行區域,每個區域被激活n次。這可能會爲n的某個值的間隔增加大量開銷(實際的時間間隔取決於許多因素)。

爲了減少開銷,將整個代碼放在一個並行區域內。因此,每個線程都會執行外部循環的所有迭代,並且內部迭代仍然會在線程之間被拆分。如果刪除了工作共享結構,那麼內部循環將不會在線程之間分配。相反,每個線程將執行內部迭代的全部外部範圍,因此例如asubsref(bin,j)將增加到num_threads而不是僅僅一次(爲什麼「最多」?提示:未受保護的併發數據訪問)。

大多數情況下,當在並行構造中運行外部循環時,需要不同的線程在相同的迭代上保持滴答。這可以通過一個屏障,在循環體的末尾來實現:

#pragma omp parallel private(i) 
{ 
    for (i = 0; i < n; i++) 
    { 
     ... 
     #pragma omp barrier 
    } 
} 

在你的情況,因爲for工作分享結構在其結束的隱式屏障明確的障礙是沒有必要的。

+0

感謝您的詳細解答! 我明白'#pragma omp for'現在做了什麼,但最外層的'for'循環如何在線程之間分配?似乎每個線程運行外部循環(意味着相同的代碼運行多次)。除非每個線程只運行'for'循環的一個迭代(如'#pragma omp for')?我的問題是:爲什麼我們不需要'#pragma omp for'作爲最外層的循環(爲什麼代碼會失敗?) – pauliwago

+0

外層循環沒有分佈。每個線程都運行全部的迭代。也許在連續迭代之間存在數據依賴性。 –

+0

如果每個線程都運行全部的迭代範圍,是不是會減慢計算機的速度? – pauliwago