2010-04-21 31 views
1

我有一個情況,如:平行的OMP內分隔部爲:OpenMP的

#pragma omp parallel for private(i, j, k, val, p, l)

for (i = 0; i < num1; i++) 
    { 
    for (j = 0; j < num2; j++) 
     { 
     for (k = 0; k < num3; k++)  
      { 
       val = m[i + j*somenum + k*2] 

       if (val != 0) 
       for (l = start; l <= end; l++) 
        { 
        someFunctionThatWritesIntoGlobalArray((i + l), j, k, (someFunctionThatGetsValueFromAnotherArray((i + l), j, k) * val)); 
        } 

       } 
     } 

     for (p = 0; p < num4; p++) 
      { 
       m[p] = 0; 
      }  
     } 

感謝您的閱讀,唷!那麼當我使用上面的(這比串行實現快3倍)時,我注意到結果(0.999967 [1]與[串行])的差別很小。現在我知道我在這裏犯了一個錯誤......特別是循環之間的連接是顯而易見的。 是否可以使用omp部分對其進行並行化?我嘗試了一些選項,如共享(p){這樣做,我得到正確的值,如在串行形式},但沒有加速。

任何關於在for循環中處理openmp編譯指示的一般建議對我來說也是非常棒的!

+0

這很難讀。它有什麼作用?某種張量收縮?你能給數學公式嗎? – Anycorn 2010-04-21 02:34:55

+0

這是一個程序的一部分,它執行線性分離的內核卷積。我會編輯它,讓它看起來更好。 – 2010-04-21 04:45:31

+0

'm'的目的是什麼?你的功能是否修改它?最內層的函數是否寫入相同的內存位置? 沒有足夠的信息來提出有意義的建議。 您需要確定可能的競爭條件。 – Anycorn 2010-04-21 05:23:15

回答

1

這實際上是對你之前的問題的重述或改進,如果你編輯過,而不是問一個「新」問題,它將有助於SOers。還是......

當你寫你的代碼的OpenMP將包裹出你最外層循環的迭代中,一個由語句

for (i = 0; i < num1; i++) 

到可用線程控制。所以,使用默認循環調度,如果你有4個線程,每個線程將執行1/4的迭代。這可能意味着線程0運行迭代i = 0,1,2,...,線程1運行迭代(num1/4)+1, (num1/4)+2,...等等。 如果您是OpenMP編程的初學者,您確實必須研究如何將循環迭代分散到各個線程中。您還必須調查修改循環調度的效果。這是瞭解並行編程的重要部分。

OpenMP將執行每個線程的內部循環,因此每個線程將執行由變量j,k,l,p控制的循環。這些將不會進一步並行化,您的程序不會實現動態線程管理。

這樣做的一個結果是,所有線程將更新m的數組m的所有值p。這對我來說並不明智。

您寫道,串行執行和並行執行的結果之間存在差異。但是你不能指定什麼結果是不同的。哪個變量在循環結尾有不同的值?一般來說,由於執行f-p運算的順序很重要,所以不應該期望在串行和並行程序上的浮點結果具有精確的相等性。 f-p算術不是真正的交換,也不是真正的聯想或真正的分配。在一般情況下,即使將數字加在一起的簡單操作也不能保證在同一程序的串行和並行執行中相同。

但是,如果不知道您報告的結果是如何計算的,那麼完全不可能說出爲什麼你會得到不同。這可能是'正常'的行爲,這可能是一個錯誤。

+0

很好說。 +1 – Anycorn 2010-04-21 17:05:39

+0

我爲告知孔道並創建一個單獨的線程表示歉意。該程序是一個相當龐大的程序,而我只處理一個部分,並且我同意我在試圖簡化它的同時失去了特殊性。 但我認爲你的描述給了我足夠的啓示,深入研究程序(和OpenMP),因爲我對OpenMP的代碼行爲沒有透徹的理解。 謝謝 Sayan – 2010-04-21 19:55:09

+0

正如你所說---「這樣做的一個後果就是所有的線程都會更新數組m的所有p值,這對我來說看起來不太明智。我用#pragma omp critical函數包裝了該部分,這使得該程序的運行時間幾乎接近序列版本。 – 2010-04-21 20:20:43