簡體   English   中英

運行 OpenMP 並行 for 循環時出現分段錯誤

[英]Segmentation fault when running an OpenMP parallel for loop

對於以下代碼,我只想並行化它的最后一部分,該部分計算每個向量的第二范數(每個向量的長度不同),但我得到了分段錯誤的錯誤。 另外,我不確定我是否在正確的地方使用了減法。

還有一點是我認為我只需要並行化外循環,內循環不需要這樣做。 正確的?

#include <iostream>
#include <vector>
#include <random>
#include <cmath>
#include <omp.h>
#include <fstream>
#include <cfloat>
#include <chrono>
using namespace std;

int main()
{
    int N = 1000000;       
    unsigned size;
    vector<vector<double>> c;
    default_random_engine g(0);
    uniform_real_distribution<double> d(0.0f, nextafter(1.0f, DBL_MAX));
    vector<double> b;
    
    for (int i = 0; i < N; i++) {
        size = pow(10, i % 4);
        vector<double> a;

        for (int j = 0; j < size; j++) {
            double number = d(g);
            a.push_back(number);
        }

        c.push_back(a);
    }       
    
    int i, j;
    double sum; 

    #pragma omp parallel for num_threads(4) shared(N) private(i,j,c,b) reduction (+: sum)
    for (int i = 0; i <N ; i++) {
       double sum = 0;
       for (int j = 0; j < c[i].size();j++) {
           sum = sum + pow(c[i][j],2);
       }

       double n = sqrt(sum);
       b.push_back(n);
    }
}

分段錯誤是由不復制向量的私有子句引起的。 它將它們初始化為默認的空向量。 如果要從“主”線程執行復制,請改用firstprivate 話雖如此, c可以在這里共享。

此外,這里有幾個要點:

  • sum必須初始化為 0(在循環外);
  • 並行循環的 scope 中的sum變量遮蔽了其外部的sum變量(同樣適用於ij );
  • 無需聲明本地sum ,OpenMP 為您完成;
  • 您可以移動a以避免不必要的副本,並在使用前保留其大小(更快);
  • N不需要在線程之間共享(最好執行本地復制);
  • 由於b是私有的,因此向其中添加值是無用的,除非在每個線程中本地讀取它(這取決於您想要做什么)。 如果要在並行區域之外讀取b ,則需要添加一個關鍵部分,以手動合並線程局部向量部分(更快),或者使用直接分配(最簡單的解決方案,可能是這里最快的解決方案)。

這是更正后的代碼:

#include <iostream>
#include <vector>
#include <random>
#include <cmath>
#include <omp.h>
#include <fstream>
#include <cfloat>
#include <chrono>
using namespace std;

int main()
{
    const int N = 1000000;
    vector<vector<double>> c;
    default_random_engine g(0);
    uniform_real_distribution<double> d(0.0f, nextafter(1.0f, DBL_MAX));
    c.reserve(N);

    for (int i = 0; i < N; i++) {
        const unsigned size = pow(10, i % 4);
        vector<double> a;
        a.reserve(size);

        for (int j = 0; j < size; j++) {
            const double number = d(g);
            a.push_back(number);
        }

        c.push_back(std::move(a));
    }

    double sum = 0.0;
    vector<double> b(N);

    #pragma omp parallel num_threads(4) firstprivate(N) shared(b,c,sum)
    {
        #pragma omp for reduction(+:sum)
        for (int i = 0; i < N ; i++) {
            double sumLocal = 0.0;

            for (int j = 0; j < c[i].size();j++) {
                sumLocal += pow(c[i][j], 2);
            }

            const double n = sqrt(sumLocal);
            b[i] = n;

            sum += sumLocal;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM