在std :: deque上并行化std :: replace

时间:2017-07-14 07:17:10

标签: c++ memory parallel-processing deque

首先,我知道双端队列中的多个写手不是很容易处理。但是使用以下算法,我可以保证元素上没有并发访问。该算法在块中划分deque(它非常大,这就是我并行化它的原因)并且std :: replaces替换deque中的值。问题是,在某些情况下,在替换任意值之后,该值似乎仍然存在(顺便说一下:新值与旧值不同)。可能是这个值没有从cpu寄存器中同步到内存吗?代码如下:

std::deque<int*> _deque;
...
int threadsCount = 25;          
int chunkSize = ceil((float) _deque.size() / (float) threadsCount);                                                                                                                          
std::vector<std::thread> threads;
for (int threadNo = 0; threadNo < threadsCount; threadNo++) {
   std::uint64_t beginIndex = threadNo * chunkSize;
   std::uint64_t endIndex = (threadNo + 1) * chunkSize;
   if (endIndex > _deque.size()) {    
      endIndex = _deque.size();      
   }
   std::deque<int*>::iterator beginIterator = _deque.begin() + beginIndex;
   std::deque<int*>::iterator endIterator = _deque.begin() + endIndex;
   threads.push_back(std::thread([beginIterator, endIterator, elementToReplace, elementNew] () {
      std::replace(beginIterator, endIterator, elementToReplace, elementNew);                                      
   }));
}
for (int threadNo = 0; threadNo < threadsCount; threadNo++) {                                                                                                                               
   threads[threadNo].join();     
}

在该算法之后,有时(不确定)被替换的(elementToReplace)值仍然在deque中。

3 个答案:

答案 0 :(得分:3)

不要手动实现这样的算法,只需传递适当的执行策略:

std::replace(std::execution::par, deque.begin(), deque.end(), elementToReplace, elementNew);
//           ^^^^^^^^^^^^^^^^^^^
//     executes the algorithm in parallel

请注意,您必须使用C ++ 17或更高版本进行编译。

答案 1 :(得分:0)

看起来像竞争条件,但我无法重现它:http://cpp.sh/5egzm 它可能取决于您正在使用的deque实现,但它看起来很奇怪

答案 2 :(得分:0)

仅供参考:由于上述算法崩溃且我的系统上仍然没有建议的执行策略,我使用了GNU parallel:

__gnu_parallel::replace(_deque.begin(), _deque.end(), elementToReplace, elementNew);

我会告诉你它是否有效以及性能统计数据。