2

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

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() 来处理复杂的参数?

4

3 回答 3

4

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

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;
}
于 2011-06-06T11:29:29.037 回答
1

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

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) 工作记忆。

于 2011-06-06T10:13:48.810 回答
0

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

于 2011-06-06T10:33:50.007 回答