2012-08-13 89 views
1

我有這個parallel for循環的OpenMP:加大對循環迭代數

struct p 
{ 
    int n; 
    double *l; 
} 

#pragma omp parallel for default(none) private(i) shared(p) 
for (i = 0; i < p.n; ++i) 
{ 
    DoSomething(p, i); 
} 

現在,有可能是內部DoSomething()p.n因爲新的元素添加到p.l增加。我想以平行的方式處理這些元素。 OpenMP手冊指出parallel for不能與列表一起使用,因此DoSomething()將這些p.l的新元素添加到按順序處理的另一個列表中,然後將其與p.l連接。我不喜歡這個解決方法。任何人都知道一個更清潔的方式來做到這一點

+0

您如何期望OpenMP在不知道會有多少人的情況下產生工作?沒有元素的元素應該如何工作?這是不可能的。 – bitmask 2012-08-13 07:50:50

+0

當所有工作完成後,再次檢查條件,如果有新的元素產生,請啓動更多工作 – Patrik 2012-08-18 11:23:24

回答

3

一個支持動態執行的構造被添加到OpenMP 3.0中,它是task構造。任務被添加到隊列中,然後儘可能併發執行。示例代碼如下所示:

#pragma omp parallel private(i) 
{ 
    #pragma omp single 
    for (i = 0; i < p.n; ++i) 
    { 
     #pragma omp task 
     DoSomething(p, i); 
    } 
} 

這會產生一個新的並行區域。其中一個線程將執行for循環,併爲每個值i創建一個新的OpenMP任務。每個不同的DoSomething()調用都將轉換爲一個任務,稍後將在空閒線程內執行。但有一個問題:如果其中一個任務向p.l添加新值,則可能在創建者線程已退出for循環後發生。這可以通過任務同步結構和外環這樣固定:

#pragma omp single 
{ 
    i = 0; 
    while (i < p.n) 
    { 
     for (; i < p.n; ++i) 
     { 
     #pragma omp task 
     DoSomething(p, i); 
     } 
     #pragma omp taskwait 
     #pragma omp flush 
    } 
} 

taskwait結構使得對於要等待的線程任務的執行,直到所有排隊。如果新元素添加到列表中,則while的條件將再次變爲真,並且會發生新一輪任務創建。 flush結構應該同步線程之間的內存視圖,例如使用共享存儲中的值更新優化的寄存器變量。

所有現代C編譯器都支持OpenMP 3.0,MSVC除外,它停留在OpenMP 2.0上。

+0

這是值得一試的。我會試一試,因爲你的答案與我所需要的最接近 – Patrik 2012-08-19 21:18:48

+0

我不需要#pragma omp並行嗎? – Patrik 2012-08-20 10:10:16

+0

第二個代碼示例僅顯示內部'single'構造。你仍然需要外部的「並行」區域。 – 2012-08-20 10:16:18