使用STL容器的OpenMP嵌套循环

时间:2015-10-07 09:04:21

标签: c++ multithreading stl openmp

我对以下关于C ++中STL容器的案例感到困惑。诸如push_back(。)之类的操作对于线程是不安全的,但是我认为可以使用STL容器。

std::vector<int> global_vector;

#pragma omp parallel for
for (int i = 0; i < height; i++)
{
 for(std::vector<int>::iterator it = fvec.begin(); it != fvec.end(); it++)
 {
   // process here with some push_back into global_vector
   global_vector.push_back(/*SOMETHING*/);
 }
}

查看上面的代码,只有forter for循环是并行的,所以我想知道内部for循环的推回是否会受到影响,使得线程不安全。

1 个答案:

答案 0 :(得分:1)

答案肯定是肯定的,现在这样的代码是线程不安全的。

原因在于,push_back()取决于并修改向量的内部状态,线程之间将存在用于修改此内部状态的竞争条件。为了使代码具有线程安全性,您需要确保不会发生对此方法的并发调用。

这可以通过这种方式强制执行:

std::vector<int> global_vector;

#pragma omp parallel for
for (int i = 0; i < height; i++) {
    for(std::vector<int>::iterator it = fvec.begin(); it != fvec.end(); it++) {
        // process here with some push_back into global_vector
        #pragma omp critical
        global_vector.push_back(/*SOMETHING*/);
    }
}

然而,这个代码在并行效率方面只是一个灾难,因为所有访问都将被序列化,同时也增加了很多管理锁的开销。所以忘记这样的方法。

然而,你可以做的是事先计算最终向量的大小,以及你真正想要访问的索引,并且只使用无状态访问函数,以及索引的每个线程脱节子集。这相当于使用global_vector[i] = /*SOMETHING*/;而不是global_vector.push_back(/*SOMETHING*/);,因为您知道i索引的每线程范围是不相交的。