[英]Segmentation fault on parallelization with OpenMP(Parallel 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(在循環外);sum
變量遮蔽了其外部的sum
變量(同樣適用於i
和j
);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.