2017-08-01 48 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矢量的整个分支,所以不用担心范围碰撞,但对其他情况很了解。 对于内存和缓存问题,我只需要测试它来确定我的情况下的效率。但指出多线程并不总是一个神奇的子弹是一件好事。 –