我有一个如下代码(简化代码):
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);
}
}
这段代码运行良好,但如果我想使用omp parallel for使其并行,我在output.push_back上遇到错误,似乎在向量调整大小时,内存已损坏。
问题是什么,我该如何解决?
如何确保任何时候只有一个线程将新项目插入到矢量中?
答案 0 :(得分:6)
std::vector
的{{1}}无法保证在以与您现在正在执行的并发方式调用时的正确行为(没有线程安全性)。
然而,由于元素不相互依赖,因此push_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);
的直接访问不依赖于operator[]
的其他成员,这可能导致线程之间的不一致。 但是此解决方案可能仍需要显式同步(即使用互斥机制等同步机制),以确保使用正确的std::vector
值。
“我怎样才能确保任何时候只有一个线程将新项目插入到矢量中?”
你不需要。线程将修改不同的元素(驻留在内存的不同部分)。您只需要确保每个线程尝试修改的元素都是正确的元素。
答案 1 :(得分:6)
简单的答案是std::vector::push_back
不是线程安全的。
为了安全地并行执行此操作,您需要进行同步,以确保不会同时从多个线程调用push_back
。
使用std::mutex
可以轻松实现C ++ 11中的同步。
答案 2 :(得分:2)
在#pragma omp critical
之前放置push_back
。
答案 3 :(得分:0)
使用并发向量
#include <concurrent_vector.h>
c ++ 11中的 Concurrency::concurrent_vector<int>
。
它是矢量的线程安全版本。
答案 4 :(得分:-8)
您可以尝试使用互斥锁来解决问题。 通常我更喜欢自己做这件事;
static int mutex=1;
int signal(int &x)
{
x+=1;
return 0;
}
int wait(int &x)
{
x-=1;
while(x<0);
return 0;
}
for( int i = 0; i < input.rows; i++ )
{
if(IsGoodMatch(input[I])
{
Newvalues newValues;
newValues.x1=input.x1;
newValues.x2=input.x1*2;
wait(mutex);
output.push_back( newValues);
signal(mutex);
}
}
希望这可以提供帮助。