【问题标题】:dot product of complex vectors with openMP复杂向量与openMP的点积
【发布时间】:2011-06-06 10:02:32
【问题描述】:

我使用的 openMP 版本不支持 reduce() 用于复杂参数。我需要一个快速的点积函数,比如

std::complex< double > dot_prod( std::complex< double > *v1,std::complex< double > *v2,int dim )

{
    std::complex< double > sum=0.;
    int i;
# pragma omp parallel shared(sum)
# pragma omp for
    for (i=0; i<dim;i++ )
    {
#pragma omp critical
        {
            sum+=std::conj<double>(v1[i])*v2[i];
        }
    }
    return sum;
}

显然,这段代码并没有加速问题,而是减慢了它的速度。对于复杂的参数,您是否有不使用 reduce() 的快速解决方案?

【问题讨论】:

  • 请注意,将并行化的 for 循环的内容放在临界区就像(甚至更糟)根本不进行并行化

标签: c++ openmp reduce dot-product


【解决方案1】:

每个线程可以作为第一步计算私有和,作为第二步,它可以组合成最终总和。在这种情况下,只有在最后一步才需要关键部分。

std::complex< double > dot_prod( std::complex< double > *v1,std::complex< double > *v2,int dim )
{
  std::complex< double > sum=0.;
  int i;
  # pragma omp parallel shared(sum)
  {
    std::complex< double > priv_sum = 0.;
    # pragma omp for
    for (i=0; i<dim;i++ )
    {
      priv_sum += std::conj<double>(v1[i])*v2[i];
    }

    #pragma omp critical
    {
      sum += priv_sum;
    }
  }
  return sum;
}

【讨论】:

    【解决方案2】:

    尝试并行进行乘法运算,然后将它们串行求和:

    template <typename T>
    std::complex<T> dot_prod(std::complex<T> *a, std::complex<T> *b, size_t dim)
    {
        std::vector<std::complex<T> > prod(dim);  // or boost::scoped_array + new[]
    
        #pragma omp parallel for
        for (size_t i=0; i<dim; i++)
            // I believe you had these reversed
            prod[i] = a[i] * std::conj(b[i]);
    
        std::complex<T> sum(0);
        for (size_t i=0; i<dim; i++)
            sum += prod[i];
    
        return sum;
    }
    

    当然,这确实需要 O(dim) 工作记忆。

    【讨论】:

    • 感谢您的快速答复!这是一个好主意,但不幸的是,它接缝使得对于 dim=10^7 的向量(我测试过),不以这种方式使用 openMP 而是使用非并行版本仍然快 3 倍。我还外包了 prod 生成,但这并没有改变这种情况。
    • @pawel:有这么大的数据集,你可能想自己编写一个 reduce 算法,正如@Christian Rau 所推荐的那样。或者找一个支持 OpenMP 的更好的编译器 reduce :)
    • @pawel_winzig:由于大向量的点积往往受到内存带宽而不是触发器的限制,这并不特别令人惊讶。
    【解决方案3】:

    为什么不让 N 个线程计算 N 个单独的总和。然后最后你只需要对 N 个总和进行求和,这可以连续完成,因为 N 非常小。虽然我不知道如何使用 OpenMP 来实现这一点,但目前(我没有任何经验),我很确定这很容易实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-05
      • 1970-01-01
      • 1970-01-01
      • 2015-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多