std :: vector push_back在并行for循环中使用时失败

man*_*ans 4 c++ parallel-processing vector openmp thread-safety

我有一个代码如下(简化代码):

for( int i = 0; i < input.rows; i++ )
{
    if(IsGoodMatch(input[I])
    { 
        Newvalues newValues;
        newValues.x1=input.x1;
        newValues.x2=input.x1*2;
        output.push_back( newValues);
    }
} 
Run Code Online (Sandbox Code Playgroud)

这段代码运行良好,但是如果我想使用omp parallel for使其并行,我在output.push_back上遇到错误,而且在向量调整大小期间,内存似乎已损坏.

有什么问题,我该如何解决?

如何确保只有一个线程可以随时将新项目插入到矢量中?

Lih*_*ihO 6

std::vectorpush_back不能保证当被称为并发的方式像你现在正在做一个正确的行为(没有线程安全).

但是由于元素不相互依赖,因此resize向量和修改循环内部元素是非常合理的:

output.resize(input.rows);
int k = 0;

#pragma omp parallel for shared(k, input)
for( int i = 0; i < input.rows; i++ )
{
    if(IsGoodMatch(input[I])
    { 
        Newvalues newValues;
        ...
        // ! prevent other threads to modify k !
        output[k] = newValues;
        k++;
        // ! allow other threads to modify k again !
    }
} 

output.resize(k);
Run Code Online (Sandbox Code Playgroud)

因为直接访问使用operator[]不依赖于其他成员std::vector可能导致线程之间的不一致.但是,此解决方案可能仍需要显式同步(即使用同步机制,如互斥锁),以确保将使用正确的值k.

"我怎样才能确保任何时候只有一个线程将新项目插入到矢量中?"

你不需要.线程将修改不同的元素(驻留在内存的不同部分).您只需要确保每个线程尝试修改的元素是正确的元素.

  • 你仍然需要使`output [k] = newValues; k ++;`atomic,或者存在竞争条件,因为两个线程都可以写入相同的`k`. (3认同)

Age*_*ien 6

简单的答案是std::vector::push_back不是线程安全的.

为了安全地并行执行此操作,您需要进行同步以确保push_back不会同时从多个线程调用.

使用a可以很容易地实现C++ 11中的同步std::mutex.