OpenMP for循环使用std :: vector和标量变量并减少

时间:2016-07-17 14:21:09

标签: c++ c++11 openmp std

我有这段代码:

#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倍!

2 个答案:

答案 0 :(得分:2)

我在三天后得到了答案,并解释了我所找到的答案。

我已经创建了我自己的缩减功能:

#pragma omp declare reduction(* : scalar : omp_out *= omp_in) initializer (omp_priv (1))

诀窍是omp_priv,显然减少值初始化很重要,有些我在here中学到了。

通过将openmp用于这样的循环,我使代码变得更加简单:

#pragma omp parallel for reduction (* : like)

非常简单干净。以这种新方式,代码得到了并行化,运行速度比我在问题体中的运行速度更快。不幸的是,它仍然比串行版本慢。也许是因为std :: vector的使用,或者重载的算术运算非常慢!?我不知道。代码是如此之大,我无法以一种可以理解的方式将其粘贴到此处,而不是为其他人阅读的痛苦。

答案 1 :(得分:1)

您的初始示例依赖于原生OpenMP减少。您确定用户定义的OpenMP减少正常吗?这可能是重载运算符的问题。

你的第二个例子是正确的(你说的)但由于关键部分而非常缓慢。为什么不通过每个线程的局部变量(例如&#34; local_like&#34;)手动实现OpenMP减少,然后在&#34; omp之后使用临界区为&#34;?