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

各スレッドは、最初のステップとしてプライベート サムを計算し、2 番目のステップとしてそれを合成して最終的な合計にすることができます。その場合、クリティカル セクションは最終ステップでのみ必要になります。

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 に答える