带有 std::vector 的 OpenMP for 循环和带缩减的标量变量
OpenMP for loop with std::vector and scalar variable with reduction
我有这个代码:
#pragma omp declare reduction(* : scalar : omp_out *= omp_in)
scalar like=1;
vector<scalar>& bigsum;
#pragma omp parallel for // reduction(* : like)
for (int m = 0; m < M-1; m++)
like *= bigsum[m];
我试图获得一致的结果,但它没有(竞争条件问题),但我应该如何解决它?因为它在代码中可见,所以我有自己的 reduction function
,但它也不起作用。我应该知道标量和 std::vector 有什么技巧吗?
这里的标量变量只是通过在我创建的每个双精度上应用 log() 来覆盖浮点数,因为有太多的双精度乘法和双精度乘法,并且其中几个的结果接近于零。例如通过执行 log() 然后乘法变为加法等等。
一致答案的一个答案是:
#pragma omp parallel
{
scalar loc = 1;
#pragma omp for
for (std::size_t m = 1; m < M;m++)
{
_flm[m-1] = Qratio[m-1] * k1 + k2;
bigsum[m-1] = kappa0omegaproduct + kappa[1] * _flm[m-1];
#pragma omp critical (reduce_product)
{
like *= bigsum[m-1];
}
}
}
这个答案是正确的,但是太慢了,在我的 8 核机器上几乎慢了 8 倍!
您的初始示例依赖于本机 OpenMP 缩减。您确定用户定义的 OpenMP 减少工作正常吗?这可能是重载运算符的问题。
你的第二个例子是正确的(你说的)但是由于临界区的原因很慢。为什么不通过每个线程有一个局部变量(例如 "local_like")然后在 "omp for"?
之后使用临界区来手动实施 OpenMP 缩减
三天后我自己有了答案,并解释了我的发现。
我创建了自己的缩减函数,如下所示:
#pragma omp declare reduction(* : scalar : omp_out *= omp_in) initializer (omp_priv (1))
诀窍是 omp_priv 显然减少值初始化很重要,这是我在 中学到的东西。
我通过像这样为循环应用 openmp 使代码更简单:
#pragma omp parallel for reduction (* : like)
非常简单干净。以这种新方式,代码得到并行化并且运行速度比我在问题正文中的代码运行得更快。不幸的是,它仍然比串行版本慢。也许是因为 std::vector 的用法,或者重载的算术运算很慢!?我不知道。代码太大了,我无法以一种可以理解的方式复制粘贴到这里,而不是让其他人阅读起来头疼。
我有这个代码:
#pragma omp declare reduction(* : scalar : omp_out *= omp_in)
scalar like=1;
vector<scalar>& bigsum;
#pragma omp parallel for // reduction(* : like)
for (int m = 0; m < M-1; m++)
like *= bigsum[m];
我试图获得一致的结果,但它没有(竞争条件问题),但我应该如何解决它?因为它在代码中可见,所以我有自己的 reduction function
,但它也不起作用。我应该知道标量和 std::vector 有什么技巧吗?
这里的标量变量只是通过在我创建的每个双精度上应用 log() 来覆盖浮点数,因为有太多的双精度乘法和双精度乘法,并且其中几个的结果接近于零。例如通过执行 log() 然后乘法变为加法等等。
一致答案的一个答案是:
#pragma omp parallel
{
scalar loc = 1;
#pragma omp for
for (std::size_t m = 1; m < M;m++)
{
_flm[m-1] = Qratio[m-1] * k1 + k2;
bigsum[m-1] = kappa0omegaproduct + kappa[1] * _flm[m-1];
#pragma omp critical (reduce_product)
{
like *= bigsum[m-1];
}
}
}
这个答案是正确的,但是太慢了,在我的 8 核机器上几乎慢了 8 倍!
您的初始示例依赖于本机 OpenMP 缩减。您确定用户定义的 OpenMP 减少工作正常吗?这可能是重载运算符的问题。
你的第二个例子是正确的(你说的)但是由于临界区的原因很慢。为什么不通过每个线程有一个局部变量(例如 "local_like")然后在 "omp for"?
之后使用临界区来手动实施 OpenMP 缩减三天后我自己有了答案,并解释了我的发现。
我创建了自己的缩减函数,如下所示:
#pragma omp declare reduction(* : scalar : omp_out *= omp_in) initializer (omp_priv (1))
诀窍是 omp_priv 显然减少值初始化很重要,这是我在
我通过像这样为循环应用 openmp 使代码更简单:
#pragma omp parallel for reduction (* : like)
非常简单干净。以这种新方式,代码得到并行化并且运行速度比我在问题正文中的代码运行得更快。不幸的是,它仍然比串行版本慢。也许是因为 std::vector 的用法,或者重载的算术运算很慢!?我不知道。代码太大了,我无法以一种可以理解的方式复制粘贴到这里,而不是让其他人阅读起来头疼。