0

我正在嘗試使用OpenMP實現並行算法。 原則上,我應該有許多線程以ashyncronous的方式寫和讀共享向量的不同組件。 有一個FOR循環,其中線程循環,當一個線程進入時,讓我們假設它在共享向量的隨機組件上寫入的循環的A行,而當它在B行時,它讀取一個隨機組件相同的共享矢量。 可能發生的情況是,一個線程會在另一個線程寫入該組件時嘗試讀取共享向量的一個組件。 如何避免不一致?OpenMP中的同步

我讀過鎖和關鍵部分,但我認爲這不是解決方案。例如,我可以在共享向量中寫入線程的A行上設置鎖定,但是如果行B中的某個線程正在嘗試讀取該組件,是否可以防止出現不一致?

+1

該向量不是線程安全的,因此您的數據競爭場景可能會發生。我認爲最好的解決方案(如果可能的話)是簡單地將矢量分成幾個部分,並將這些部分分配給不同的線程。這樣,您不需要任何鎖或原子,因爲每個線程都有其自己的矢量子部分。 –

+1

「讓我們假設,循環中的A行寫在共享向量的隨機組件上,而當它在行B中時,它讀取同一共享向量的隨機組件:」不管可能的不一致性如何,您的算法是否具有彈性到那個?我的意思是,對「共享矢量的隨機分量」進行讀寫操作的順序是否對最終結果有嚴重影響?如果是的話,也許你的算法畢竟不是可並行化的(這種方式)。如果不是,那麼可能有一個解決方案。只需發佈一個工作順序版本,我們就會看到。 – Gilles

+0

請顯示[你想做的最簡單但有效的例子](http://stackoverflow.com/help/mcve)。至少顯示標量代碼。 –

回答

2

如果向量修改是非常簡單的單值賦值操作,並且實際上不是函數調用,那麼您需要的可能是原子讀取和寫入。對於原子操作,從同時寫入的數組元素的讀取將返回新值或先前的值;它永遠不會返回某種舊的和新的價值混搭。 OpenMP爲此提供了atomic構造。在包括x86在內的某些體系結構中,原子系統比關鍵部分輕巧得多。

隨着更復雜的修改,你必須使用關鍵部分。這些可以是有名的或匿名的。後者使用

#pragma omp critical 
code block 

匿名臨界區都映射到相同的同步對象,無論什麼在源代碼中的構建體的位置創建的,因此可能的是不相關的代碼段,以獲得與所有可能的同步不良影響,如性能下降甚至意外死鎖。這就是爲什麼總是使用命名的關鍵部分。例如,下面的兩個代碼段將得到同步:

// -- thread i --     // -- thread j -- 
...        ... 
#pragma omp critical(foo) <  #pragma omp critical(foo) 
do_something();   <  do_something; 
...        ... 
#pragma omp critical(bar)   #pragma omp critical(bar) < 
do_something_else();    do_something_else();  < 
...        ... 

(代碼當前正由每個線程被標記<執行)

注意,臨界區結合的所有線程程序,而不考慮線程所屬的團隊。這意味着即使是在不同平行區域執行的代碼(使用嵌套並行時主要出現的情況)也會同步。