2017-08-01 43 views
2

我試圖把一個(非常)大的矢量,並將其中的所有值重新分配到多維(2D)矢量>中。正在向多維向量中的子元素寫入線程安全的元素嗎?

爲了避免重新分配,多維向量的兩個維都調整爲正確的大小,以避免重新分配。

目前,我正在做它單線程,但它是需要重複發生的事情,並且由於大尺寸(〜7秒)非常緩慢。問題是,對於我來說,是否對於每個2D元素使用線程是否是線程安全的。

一些僞代碼:

vector<string> source{/*assume that it is populated by 8,000,000 strings 
of varying length*/}; 
vector<vector<string>> destination; 

destination.resize(8); 
for(loop=0;loop<8;loop++)destination[loop].resize(1000000); 

//current style 
for(loop=0;loop<source.size();loop++)destination[loop/1000000][loop%1000000]=source[loop]; 

//desired style 
void Populate(int index){ 
    for(loop=0;loop<destination[index].size();loop++)destination[index][loop]=source[index*1000000+loop]; 
} 

for(loop=0;loop<8;loop++)boost::thread populator(populate,loop); 

認爲該線程版本應該工作,因爲他們正在寫分隔第二維元素。但是,我不確定編寫字符串是否會破壞事情,因爲它們正在調整大小。

回答

1

當只考慮線程安全性時,這很好。

Writing concurrently to distinct objects is allowed。即使它們是結構體中的相鄰字段或同一數組中的元素,C++也會將對象視爲不同的。該對象的數據類型在這裏並不重要,所以這對於string也是如此,對於int也是如此。唯一重要的是你必須確保你的操作範圍真的完全不同。如果有任何重疊,您的手上就會有數據競賽。

但是,這裏還有另外一件事要考慮,那就是性能。這是高度依賴於平臺的,所以語言標準在這裏不給你任何規則,但是有一些效果需要注意。例如,數組中的相鄰元素可能駐留在同一緩存行中。因此,爲了使硬件能夠實現語言的線程安全保證,它必須同步對這些元素的訪問。例如:以一個線程處理所有具有偶數索引的元素的方式對數組進行分區訪問,而另一個對奇數索引進行處理的技術上是線程安全的,但是會對硬件造成很大壓力,因爲兩個線程都可能會競爭用於存儲在同一緩存行上的數據。

同樣,你的情況存在於存儲器總線上。如果你的線程能夠以比你能夠將它們寫入內存更快的速度完成數據的計算,那麼你可能實際上並沒有通過使用多線程獲得任何東西,因爲所有線程最終都會等待內存。

確定並行性是否真的是解決問題的正確方案時,請牢記這些事情。

+0

非常感謝您對所有評論的清晰深入的解釋以及一些需要注意的細節。 在我的情況下,每個線程都會獲得2D矢量的整個分支,所以不用擔心範圍碰撞,但對其他情況很瞭解。 對於內存和緩存問題,我只需要測試它來確定我的情況下的效率。但指出多線程並不總是一個神奇的子彈是一件好事。 –