2017-01-13 9 views
0

2つの3次元配列の最大絶対差をC++ AMPと比較したいと思います。AMP C++で配列の最大値を計算する

OpenMPを使用すると簡単です。 2つのアレイ

float*** u, ***uOld; 

コードは考慮:

double residual = 0; 
#pragma omp parallel for schedule(static) collapse(3) reduction(max : residual) 
for (int i = 0; i < nbX; i++) 
    for (int j = 0; j < nbY; j++) 
     for (int k = 0; k < nbTheta; k++) 
      residual = std::max(residual, fabs(u[i][j][k] - uOld[i][j][k])); 

AMPアルゴリズムからmax_elementを使いやすいであろうが、それは実装されていません。私はこのような何かを考えるが、減少は、外側のループレベルで必要とされている:

extent<1> extTheta(nbTheta); 
parallel_for_each(extTheta, [=, &u_, &uOld_](index<1> iTheta) restrict(amp) 
{ 
    type residual = 0; 
    for (int iX = 0; iX < nbX; iX++) 
    for (int iY = 0; iY < nbY; iY++) 
    residual = fast_math::fmax(residual, fast_math::fabs(u_[iX][iY][iTheta] - uOld_[iX][iY][iTheta])); 
}) 

データはGPU上で、私は、効率上の理由から、GPU上のトランジットにそれを望んでいません。どのように効率的にそれを行うには?

答えて

0

はここでMSDNのブログからインスピレーションを得たソリューションです:問題のスニペットとは異なりhttps://blogs.msdn.microsoft.com/nativeconcurrency/2012/03/08/parallel-reduction-using-c-amp

parallel_for_each(extent<3>(nbTheta, nbX, nbY), [=, &u_, &uOld_](index<3> idx) restrict(amp) 
{ 
    uOld_[idx[0]][idx[1]][idx[2]] = abs1(u_[idx[0]][idx[1]][idx[2]] - uOld_[idx[0]][idx[1]][idx[2]]); 
}); 


array_view<float, 1> residualReduce_ = uOld_.view_as<1>(extent<1>(nbTheta*nbX*nbY)); 
array_view<float, 1> residual_ = residualReduce_.section(index<1>(0), extent<1>(1)); 
for (unsigned shift = nbTheta*nbX*nbY/2; shift > 0; shift /= 2) 
{ 
    parallel_for_each(extent<1>(shift), [=](index<1> idx) restrict(amp) 
    { 
     residualReduce_[idx[0]] = fast_math::fmax(residualReduce_[idx[0]], residualReduce_[idx[0] + shift]); 
     if (shift % 2){ //If odd, each thread includes a shifted entry. One will match the end of the queue 
      residualReduce_[idx[0]] = fast_math::fmax(residualReduce_[idx[0]], residualReduce_[idx[0] + shift + 1]); 
     } 
    }); 
} 
concurrency::copy(residual_, &residual); 
parallel_for_each(extent<3>(nbTheta, nbX, nbY), [=, &u_, &uOld_](index<3> idx) restrict(amp) 
{ 
    uOld_[idx[0]][idx[1]][idx[2]] = u_[idx[0]][idx[1]][idx[2]]; 
}) 

、解決策はU.

にuOldの更新が含ま減少が最も効率的ではありませんしかし、残りのコードと比較してもまだ高速です。

関連する問題