2015-09-21 194 views
11

我有一個需要執行的功能n=1000次。此功能進行蒙特卡羅風格模擬,並返回int作爲結果。我想並行運行nthreads=4。每當一個線程完成一個循環時,它應該將結果放入std::vector<int>。 因此,在1000個週期後,我有一個1000 int s的矢量,可以通過統計檢查。我可以做一個線程安全的std :: atomic <vector<int>>嗎?

由於std::vector不是線程安全的,所以我想到了std::mutex(這肯定會起作用)。

但我不知道我是否可以聲明一個向量是原子的,從而解決互斥? 是否有可能有std::atomic<std::vector<int>>?我可以使用push_back等嗎?

+0

是否編譯過std :: atomic >? – DawidPi

+0

我不能在這臺機器上嘗試...但只是遇到原子。 – dani

+0

我只是想補充一點,如果你從一開始就知道你將有1000次執行,並且你的容器將存儲1000個結果,那你爲什麼要使用動態容器?我知道std :: vector在它的實現中使用了數組,如果你在開始時保留足夠的空間,那麼不需要重新分配(所以使用std :: array將不會有任何性能增益)。 – dptd

回答

8

你不需要。這是完全沒關係,可以從多個線程訪問JA std::vector,如果

  • 你讀
  • 你寫不同對象
  • 對象

所以只要確保你創建一個大小的矢量n=1000並根據你的線程號碼(1到4),你分配元素0-249,250-499等到你的線程。

所以你的每個線程計算n/nthreads元素。

+9

在向線程分配部分線程之前,向量適當調整大小非常重要 - 任何調整大小絕對不會是線程安全的。 – Jeremy

+1

但是,即使你這樣做,你仍然需要在讀者和作者之間進行同步。特別是,但不是唯一的原因,因爲不能保證在所有體系結構中訪問'int'都是原子的,除非使用'atomic_int'或'std :: atomic '。 – blubberdiblub

4

原子可以實例化與trivially可複製類型。向量不是這種類型。

+0

問題不是答案。請將問題發送給OP,作爲對問題的評論 – Gombat

+0

是像'int k [1000]'一個「可微複製類型」的C風格數組嗎? – dani

+0

'k'只是一個指針。指針是可複製的。但是我不知道這個表是否是線程安全的,因爲'k'是一個普通的指針,但'k [5]'可以寫成*(k + 5)','k + 5'一個不同的指針,但我不確定它是否真的。你可以從'std'中檢查'is_trivially_copyable'。您通常會爲線程安全容器編寫自己的'threadsafe_vector'類型。 – DawidPi

13

C++ 11§29.5/ 1說

有一個通用類模板原子。模板參數T的類型應是可複製的(3.9)。

可微複製的意思是什麼?

§3.9告訴

標量類型,能夠複製平凡類類型(第9節),這樣類型的數組,並且這些類型(3.9.3)的CV-合格版本平凡統稱可複製類型。

對於類類型(其中std::vector是):

甲平凡能夠複製類是一類:

  • 沒有非平凡的拷貝構造
  • 沒有非平移移動構造函數
  • 沒有非平凡的複製賦值運算符
  • 沒有非平凡的舉動賦值運算符
  • 有一個平凡的析構函數

根據這份名單std::vector不平凡可複製,所以你不能使用std::atomic<std::vector<int>>

既然你知道的大小提前,因爲你不需要使用將需要載體的方法在不同的位置被重新分配(如push_back)。您可以使用std::vector<int>::resize或尺寸構造預分配和preconstruct所需int秒。因此,你的併發線程不需要對向量本身,而是對元素進行操作。

如果沒有來自不同線程訪問相同的元素,沒有競爭條件。

這同樣適用於int k[1000]這是可複製的。但你不需要它是因爲t他的線程不會改變數組/矢量/列表本身,而是改變元素。

相關問題