OpenMP 出现分段错误(核心已转储)

use*_*269 1 g++ openmp

我在使用 OpenMP 并行化代码时遇到问题。我附上了可以重现我的问题的最简单的代码。

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int n = 10;
    int size = 1;

    vector<double> vec(1, double(1.0));
    double sum = 0.0;

#pragma omp parallel for private(vec) reduction(+: sum)
    for (int i = 0; i != n; ++i)
    {
        /* in real case, complex operations applied on vec here */

        sum += vec[0];
    }

    cout << "sum: " << sum << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我使用带标志 -fopenmp 的 g++ 进行编译,g++ 的错误消息提示“分段错误(核心已转储)”。我想知道代码有什么问题。

请注意,应将其设置为私有,因为在实际代码中,for 循环中vec应用了复杂的操作。vec

Mic*_*emm 5

问题确实出在private(vec)条款上。这段代码有两个问题。

首先,从语义的角度来看,private(vec)应该是shared(vec),因为其意图似乎是std::vector并行地处理同一个实例。所以,代码应该如下所示:

#pragma omp parallel for shared(vec), reduction(+: sum)
for (int i = 0; i != n; ++i)
{
    sum += vec[0];
}
Run Code Online (Sandbox Code Playgroud)

在前面的代码中,为每个线程private(vec)创建了一个私有实例std::vector,并应该通过调用 的默认构造函数来初始化这些实例std::vector

vec[0]其次,分段错误是由于任何私有实例中都没有元素这一事实而引起的。这可以通过调用vec.size()线程来确认。

PS:无论如何,shared(vec)这将是vecOpenMP 规范的默认共享。

  • 如果您需要“std::vector”的私有实例,那么您可能会考虑“firstprivate(vec)”,但随后您将获得每个线程的原始向量的副本构造副本。因为我不知道你想要实现什么目标,所以我不确定这最终是否会对你有用。 (2认同)