Omp for循环初始化向量

时间:2019-03-09 12:45:38

标签: c++ for-loop parallel-processing openmp

我有以下代码:

int main() {
vector<int> vec;

#pragma omp parallel for ordered schedule(dynamic)            
for (int i = 0; i <= 300; i++) {
    vec.push_back(i);
} 
cout << vec.size() << endl;
}

向量大小有时为285或294,但从不为301。我做错了什么?

1 个答案:

答案 0 :(得分:2)

您在这里看到的是多个线程调用的线程不安全函数的影响。内部push_back在伪代码中执行以下操作

if reallocation needed:
    reallocate
construct new object at &data[size]
++size

现在尝试想象不同的线程同时运行上述代码。如果两个线程都看到需要重新分配并尝试同时进行分配,会发生什么情况。如果他们俩都在&data[size]之前到达了该点,那么他们都在++size处构造了一个对象怎么办?请注意,即使尝试在与构造相同的行上进行增量也行不通,因为它们仍然是独立的非原子操作。

您真正想做的是创建一个严格的线程安全操作循环,如下所示。

int main() {
    std::vector<int> vec(301);

    #pragma omp parallel for
    for (int i = 0; i <= 300; i++) {
        vec[i]= i;
    }
    std::cout << vec.size() << std::endl;
}

在这种情况下,每个线程都使用唯一的vec[i]访问i。因此,不会对同一对象同时进行任何操作。这绝对安全。

要回答您的后续问题,没有办法将push_back同时并入向量。您将不得不同步您的push_back调用,这将使它们比非并行方式慢。另一种解决方案是填充线程本地容器,然后合并它们。但是,只要我上面显示的简单解决方案适用,它就会比其他解决方案更快。