c++ - 带有 STL 容器的 OpenMP 嵌套循环

标签 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*/);
 }
}

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

最佳答案

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

原因是,push_back()依赖并修改vector的内部状态,修改这个内部状态的线程之间会出现race condition。要使代码线程安全,您需要确保不会发生对此方法的并发调用。

这可能会以这种方式强制执行:

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*/);
    }
}

但是,就并行效率而言,这段代码将是一场灾难,因为所有访问都将被序列化,同时还会增加大量用于管理锁的开销。所以忘掉这种方法吧。

然而,您可以做的是提前计算最终 vector 的大小,以及您真正想要访问的索引,并且仅使用无状态访问函数,以及在每个线程上不相交的索引子集。这将对应于使用 global_vector[i] =/*SOMETHING*/; 而不是你的 global_vector.push_back(/*SOMETHING*/); 因为你知道 per- i 索引的线程范围是不相交的。

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

相关文章:

c# - 如何确保部分代码(包含异步)只被调用一次?

c - 如何阻塞信号量直到其值为正数

c++ - STL 正确使用 find_if() 打印出奇数

c++ - STL::Map - 遍历列表还是使用查找?

c++ - 为什么这3行代码是对的?关于*p

c++ - 想要构建一些必要的库来进行特征检测。有一些错误

c++ - 向 VBO 发送单个 unsigned int

java - 多线程编程中的公平性是什么?

c++ - std::unordered_map 析构函数不释放内存?

c++ - Qt5:一次性连接到 lambda