对于下面的代码,我只想并行化其计算每个向量的第二个范数的最后一部分(每个向量的长度不同),但我收到了分段错误的错误。 另外,我不确定我是否在正确的地方使用了减少的总和。
还有一点是,我认为我只需要并行化外层循环,内层循环不需要这样做。对吗?
#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);
}
}
答案 0 :(得分:3)
分段错误是由不复制向量的私有子句引起的。它将它们初始化为默认的空向量。如果您想从“主”线程执行复制,请改用 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;
}
}
}