2012-01-04 117 views
2

我對於並行編程相對較新,希望通過openmp完成C++中的以下任務。通過不同線程之間的(C++)openmp共享信息

我有一些(可以說4)相對複雜的對象/計算要做。它們都是相似的,但是太複雜以致無法並行化每一個(所以它們運行串行)。所以我的想法是爲它們中的每一個使用不同的線程/ CPU,這意味着我想將計算分攤到我的核心上。儘管在這種情況下這可能不是最有效的並行性用法,但它可能是最容易實現的(因爲每個計算的高複雜度)。

雖然這由

#pragma omp parallel 
{ 
    #pragma omp for 
    for(int i = 0; i < 4; i++) 
    { 
     obj[i].calculate();  
    } 
} 

欲這個對象之間交換的信息,例如一個整數(或更復雜的對象)的工作「一個」應被每個計算過程中修改(雖然我可以不預測何時和多少次,但尤其多於一次)。如果它被修改,那麼這些信息也需要併入其他計算中。儘管信息的具體交換(再次)是相對複雜的,但這也是通過「計算」方法(隱含地)完成的。一般來說,這應該看起來像上面,如果加上整數「一」,這是所有的計算方法寫和讀:

int a; 
#pragma omp parallel 
{ 
    #pragma omp for 
    for(int i = 0; i < 4; i++) 
    { 
     obj[i].calculate();  
    } 
} 

所以我的問題是,如何防止「數據種族」在「一」?這意味着我怎樣才能生成一個對象,每次只能由一個線程訪問,而不用在「計算」方法本身中詳細討論? openmp是否提供了這個功能,如果沒有,這個庫是用來做什麼的?

此致敬意!

+0

鎖定'一個'的整個時間任何計算將需要它是相當簡單的,但這將有效地序列化您的計算,是嗎?你所有的計算都能夠通過另一個線程異步改變可能複雜的'a'(我懷疑不是!)嗎?如果不是,是否可以在每個計算中確定哪些點是安全的,以便他們接受新的'a'?如果他們在某個中間點接受新的'a',這是否會使計算運行的結果無效? – 2012-01-04 10:30:23

+0

我不確定我是否瞭解您的評論。計算可能是「長」(最多幾天),「a」具有額外的特性,關於「更新」的知識可能會節省相當長的時間,但功能並不需要。所以檢查一個新的「a」會經常重複,但大部分時間都會消極(沒有新的「a」)。所以一個「舊」「一個」不會造成傷害,但是一個錯誤(異步?)會。在我看來,問題在於從一個線程修改「a」,而從另一個線程讀取。 – Martin 2012-01-04 10:47:12

+0

我的問題在於理解如何改變參數(即使'乾淨'地完成'原子'來改變'a'),在計算的某個中間階段和未知階段可能會導致任何問題 - 一些計算將與舊的'a'和一些新的'a'一起完成 - 對我來說,這將是一件壞事。然而,你的回覆標誌着一些重要的信息 - 計算要求在適當的時候提供一個新的'a'(儘管如果現在沒有'a'可用,請求可能會被拒絕)。這使事情變得更容易。 – 2012-01-04 11:03:23

回答

0

當然,您意識到方法calculate無法訪問您發佈的代碼中的變量a。如果你想這樣的工作,你可以寫你的計算功能,內聯和使用時要修改a關鍵部分:

int a; 
#pragma omp parallel 
{ 
    #pragma omp for 
    for(int i = 0; i < 4; i++) 
    { 
     // code of calculate 
     #pragma omp critical 
     { 
      // modify a 
     } 
     // other code 
    } 
} 
+0

在實際代碼中,通過calculate方法中的(回調)指針訪問「a」。計算函數非常長,並且在一定程度上不可預測運行時。此外,在每次計算過程中,「a」需要多次,所以我不能等待整個計算過程。所以我不確定內聯是否足夠。 – Martin 2012-01-04 10:51:39

+0

@Martin:我只是建議把修改的關鍵部分放在一個地方,而不是把它放在計算的末尾。 – Tudor 2012-01-04 10:57:35

+0

hm閱讀這些評論,您很可能需要在計算方法中添加指令以確保正確更新。 – Bort 2012-01-04 11:02:10

1

從你的描述來看,我不知道並行執行是否會幫助你在任何時候每個線程必須等待更新信息a

無論如何,您可以使用flushatomiccritical指令更新沒有競爭條件的變量。最好的選擇很大程度上取決於哪些線程必須更新a或更新a

critical:所有線程執行的代碼,但每一次一個

atomic:內存是針對多次寫入保護,在內部被critical

flush代替:更新共享變量,並含蓄地critical稱爲

最後,barrier確保所有線程都已達到代碼中的相同點。

我希望每個計算期間該對象之間進行交換的信息,用於 例如一個整數(或更復雜的對象)的「a」應該被修改 (雖然我無法預測的時間和頻率, 但特別多於一次)。

這個說法有點刺激,因爲你應該知道什麼時候需要你的更新a。當您這樣做時,您需要在所有線程中都有障礙,在臨界區域更新a並繼續並行執行。那麼有多少線程更新a?主線程還是全部?

如果只有一個線程必須更新a,那麼另一個選項是single指令。它的代碼只能由一個隱含屏障的線程執行,並在執行後隱式刷新。這些是正確更新複雜對象a到所有線程的一般選項。祝你好運。

+0

+1,從我目前看到的,指針/ s的原子更新似乎應該完成這項工作。如果'a'是隻讀的計算器,一個靜態指針可以適用於所有的線程,只要它們在它們的檢查點創建本地副本並且'舊''a不會被銷燬。 – 2012-01-04 11:31:51