我正在尝试使用 OpenMP 执行并行代码,但在编译时出现段错误错误。代码如下:
int i, j;
vector<double> xcentro, ycentro, zcentro, x, y, z, r, d;
#pragma omp parallel for num_threads(4)
for (i = 0; i != xcentro.size() - 1; i++)
{
//Inicio el valor de r[i] a un valor muuuy grande, muy superior al que pueda tener la máxima esfera de todas
r.insert(r.begin() + i, 10000000);
for (j = 0; j != x.size() - 1; j++)
{
d.insert(d.begin() + j, sqrt((xcentro[i] - x[j])*(xcentro[i] - x[j]) + (ycentro[i] - y[j])*(ycentro[i] - y[j]) + (zcentro[i] - z[j]*(zcentro[i] - z[j]))));
if (d[j] < r[i])
{
r[i] = d[j];
}
}
}
谁能帮帮我? 此外,我不知道我的代码是否适合并行化。
答案 0 :(得分:1)
我稍微清理了您的代码。同时我发现并更正了距离计算中的一个错误:在错误的位置有一个)
。我也很怀疑你忽略了 xcentro
和 x
的最后一个元素。我想你会想要使用例如x.size()
而不是 x.size() - 1
无处不在,不忽略最后一个元素。
vector<double> get_r(vector<double> const &xcentro,
vector<double> const &ycentro,
vector<double> const &zcentro,
vector<double> const &x,
vector<double> const &y,
vector<double> const &z) {
vector<double> r(xcentro.size(), 10000000);
#pragma omp parallel for num_threads(4)
for (int i = 0; i < xcentro.size(); ++i)
{
// maybe try "#pragma omp simd" here
for (int j = 0; j < x.size(); ++j)
{
double const d =
sqrt((xcentro[i] - x[j]) * (xcentro[i] - x[j]) +
(ycentro[i] - y[j]) * (ycentro[i] - y[j]) +
(zcentro[i] - z[j]) * (zcentro[i] - z[j]));
if (d < r[i])
{
r[i] = d;
}
}
}
return r;
}
vector
容器通常不是线程保存的(假设这是 std::vector
),因此不能使用任何可能重新分配容器的成员函数,例如 insert
。将 insert
移入 d
时,即使没有并行性,您的代码也很有可能运行得更快,因为 j
之后的所有元素甚至必须复制到一个位置,当为插入的元素分配了足够的内存。
事实上,串行版本可能更快,因为此工作负载受内存限制,这意味着它没有包含足够的与内存读取和写入数量相关的计算,无法根据您的硬件从并行化中获利。
答案 1 :(得分:0)
当插入到你的向量时,你会增加超过向量末尾的迭代器。例如
r.insert(r.begin() + i, 10000000);
取向量 r
的开头并将其增加 i
位。然而,此时向量 r
还不够大,因为代码在多个线程上并行化。
因此,例如,其中一个线程可能会尝试插入到位置 r.begin() + 2
,而 r
只有 1 个元素。
你可以通过像这样预先分配你的向量来解决这个问题:
std::vector<double> r(SOME_NUMBER)
然后将其索引为 r[i]
。
或者相反,您可以使用 push_back
代替 insert,但请记住,插入的顺序可能会打乱。