std::vector push_back 在并行 for 循环中使用时失败
std::vector push_back fails when used in a parallel for loop
>我有一个代码如下(简化代码(:
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 使其并行,我在output.push_back上遇到错误,似乎在矢量调整大小期间,内存损坏了。
问题是什么,我该如何解决?
如何确保任何时候只有一个线程将新项目插入 vector?
简单的答案是std::vector::push_back
不是线程安全的。
为了安全地并行执行此操作,您需要同步以确保不会同时从多个线程调用push_back
。
C++11 中的同步可以通过使用 std::mutex
轻松实现
std::vector
的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
的其他成员,这可能会导致线程之间的不一致。但是,此解决方案可能仍需要显式同步(即使用互斥锁等同步机制(,以确保使用正确的k
值。
"我怎样才能确保任何时候只有一个线程将新项目插入 vector?">
你不需要。线程将修改不同的元素(驻留在内存的不同部分(。您只需要确保每个线程尝试修改的元素是正确的。
使用并发向量
#include <concurrent_vector.h>
Concurrency::concurrent_vector<int>
C++11 中。
它是矢量的线程安全版本。
在push_back
之前放一个#pragma omp critical
。
我通过派生标准std::vector
类来解决了一个类似的问题,只是为了实现一个适合在OpenMP
范式中工作的atomic_push_back
方法。
这是我的"OpenMP-safe"矢量实现:
template <typename T>
class omp_vector : public std::vector<T>
{
private:
omp_lock_t lock;
public:
omp_vector()
{
omp_init_lock(&lock);
}
void atomic_push_back(T const &p)
{
omp_set_lock(&lock);
std::vector<T>::push_back(p);
omp_unset_lock(&lock);
}
};
当然,您必须包括omp.h
.然后,您的代码可能如下所示:
opm_vector<...> output;
#pragma omp parallel for shared(input,output)
for( int i = 0; i < input.rows; i++ )
{
if(IsGoodMatch(input[I])
{
Newvalues newValues;
newValues.x1=input.x1;
newValues.x2=input.x1*2;
output.atomic_push_back( newValues);
}
}
如果你仍然需要代码的非并行部分中其他地方的output
向量,你可以使用普通的push_back
方法。
您可以尝试使用互斥锁来解决问题。通常我更喜欢自己实现这样的事情;
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);
}
}
希望这能有所帮助。
- C/C++:socket() 创建在循环中失败,打开的文件太多
- 谁能弄清楚为什么我的循环会失败?
- 断言失败:列出迭代器不可递增(不在循环中)
- 对于循环执行失败,因为变量我不会递增,为什么?
- GCC自动矢量化在减少循环中失败
- 密码检查程序-匹配密码失败-循环失败
- c++ 中带有容器迭代器的循环类型依赖关系(GCC 失败,而 MSVC 正常)
- 线程未正确结束:它忽略失败的循环条件
- 在循环中第二次调用luaT_pushudata时失败
- 在for循环内部使用setw是失败的
- 用于循环计数器失败的 C++
- 输入验证循环在第一次输入失败后无法正常工作
- std::vector push_back 在并行 for 循环中使用时失败
- 循环迭代后共享指针断言失败
- 对于循环不递增或循环不失败测试
- fgetwc EOF 循环测试失败,但 65535 正常
- 在字符串上循环以查看字符串失败的位置
- 当循环失败时,当读取int和字符串C++时
- 迭代器结束检查在“for”循环内递增后失败
- c++编程,登录尝试,while循环失败