我对以下有关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循环的回推是否会受到影响,从而使线程不安全。

最佳答案

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

原因是,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索引的每个线程范围是不相交的。

关于c++ - 带有STL容器的嵌套式OpenMP循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32988080/

10-10 22:42