如果向量修改是非常簡單的單值賦值操作,並且實際上不是函數調用,那麼您需要的可能是原子讀取和寫入。對於原子操作,從同時寫入的數組元素的讀取將返回新值或先前的值;它永遠不會返回某種舊的和新的價值混搭。 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(); <
... ...
(代碼當前正由每個線程被標記<
執行)
注意,臨界區結合的所有線程程序,而不考慮線程所屬的團隊。這意味着即使是在不同平行區域執行的代碼(使用嵌套並行時主要出現的情況)也會同步。
該向量不是線程安全的,因此您的數據競爭場景可能會發生。我認爲最好的解決方案(如果可能的話)是簡單地將矢量分成幾個部分,並將這些部分分配給不同的線程。這樣,您不需要任何鎖或原子,因爲每個線程都有其自己的矢量子部分。 –
「讓我們假設,循環中的A行寫在共享向量的隨機組件上,而當它在行B中時,它讀取同一共享向量的隨機組件:」不管可能的不一致性如何,您的算法是否具有彈性到那個?我的意思是,對「共享矢量的隨機分量」進行讀寫操作的順序是否對最終結果有嚴重影響?如果是的話,也許你的算法畢竟不是可並行化的(這種方式)。如果不是,那麼可能有一個解決方案。只需發佈一個工作順序版本,我們就會看到。 – Gilles
請顯示[你想做的最簡單但有效的例子](http://stackoverflow.com/help/mcve)。至少顯示標量代碼。 –