2012-12-26 135 views
0

我是OpenMP的新手,並且從我已閱讀的有關Microsoft Visual Studio 2010標準的OpenMP 2.0中,全局變量在並行編程中使用時被認爲是麻煩和容易出錯的。我也一直採用這種感覺,因爲我很少發現如何有效地處理全局變量和靜態全局變量,或者根本就沒有處理這個問題。C++ OpenMP for-loop全局變量問題

我有這段代碼運行,但由於在並行塊中創建的局部變量,我沒有得到我正在尋找的答案。我得到8種不同的打印輸出(因爲我在PC上有多少個線程)而不是1個答案。我知道這是因爲在並行塊中創建了局部變量「list」,但如果我移動「list」變量並使其成爲全局變量,則此代碼將不會運行。其實代碼確實運行,但它從來沒有給我一個答案。這是我想的示例代碼修改爲使用一個全球性的「列表」變量:

#pragma omp parallel 
{ 
    vector<int> list; 
#pragma omp for 
    for(int i = 0; i < 50000; i++) 
    { 
     list.push_back(i); 
    } 
    cout << list.size() << endl; 
} 

輸出:

6250 
6250 
6250 
6250 
6250 
6250 
6250 
6250 

他們增加了50000,但我沒有得到一個答案用50000,而是分開了。

解決方案:

vector<int> list; 
    #pragma omp parallel 
{ 
    #pragma omp for 
    for(int i = 0; i < 50000; i++) 
    { 
     cout << i << endl; 
    #pragma omp critical 
     { 
      list.push_back(i); 
     } 
    } 
} 
cout << list.size() << endl; 

回答

1

按照MSDN Documentation平行子句

定義並行區域,其是將通過並行 多個線程執行的代碼。

而且由於該表變量本節內聲明的每個線程都有自己的名單。

在另一方面,for pragma

導致在完成用於環路並行區域內的工作得以 線程分割。

因此,50000次迭代將在線程中拆分,但每個線程都有自己的列表。 我想你正在嘗試做的可以通過以下方式實現:

  1. 以列表定義「平行」部分之外。
  2. 使用critical section保護list.push_back語句。

試試這個:

vector<int> list; 
#pragma omp parallel 
{ 
#pragma omp for 
    for(int i = 0; i < 50000; i++) 
    { 
#pragma omp critical 
     { 
      list.push_back(i); 
     } 
    } 
} 
cout << list.size() << endl; 

我不認爲你應該得到的OpenMP任何加速在這種情況下,因爲那裏將是關鍵的一節的爭奪。對於這個更快的解決方案(如果你不關心元素的順序)將是每個線程都有自己的列表,並在循環結束後合併這些列表。在這種情況下,使用std :: list而不是std :: vector的實現看起來更乾淨(因爲你不必複製數組)。

一些應用程序是內存綁定的,而不是計算綁定。底線:檢查你是否真的從OpenMP獲得加速。

+0

是你的權利沒有明顯的加快與解決這個問題的實現。即使我沒有嘗試過你的「合併」解決方案,我也喜歡它的聲音。我期待將這個應用到更大的項目,我只是獲得一些經驗,但「合併」解決方案正是我所期待的。 – arnm

+0

如果我記得我會回來並將您的建議發佈在我的結果上。謝謝! – arnm

+1

@cstuts:在並行區域之前預先分配足夠的內存並使用list [i] = i而不是'omp critical {list.push_back(i)}'可能會更快。 – jfs

0

爲什麼你需要在這裏的第一個編譯? (#pragma omp parallel)。我認爲這是問題。

+0

我認爲,如果你刪除第一編譯你的程序將在單個線程中運行... –