2016-04-19 4 views
1

私はこの単純なループをCUDAで実現したいと思います。CUDAでのシーケンシャルプログラミング

for (int i = 1; i <= N; i++) 
    { 
     for (int j = 1; j <= N; j++) 
     { 
     x[i, j] = (x0[i, j] + a*(x[i - 1, j] + x[i + 1, j] + x[i, j - 1] + x[i, j + 1]))/c; 
     } 
    } 

問題は次のとおりです。 X [i、j] X(i-1、j)とX [i、j-1]の新しい値を知る必要がある。しかし、GPUはすべてを並列に計算しているので、CPUとGPUから受け取った結果は異なります。私はCUDAとcudaDeviceSynchronize()について動的パラレル化についての情報を見つけましたが、それは有用かもしれませんが、とにかくカーネルにこのループを実装する方法はまだ分かりません。私はあなたの助けに感謝します。

+1

フィルターを実装しましたか?その場合は、CPUのコードが間違っています。ソースデータを計算する前にコピーする必要があります – Joe

+1

別のスレッドによって並列に変更された可能性のあるデータにアクセスしていることを考えれば、最も単純な回避策は1つのバッファから値を読み取ることです"入力")、あなたの計算を別のものに書きます( "出力")。 これは、ぼかしや中央値など、隣接ピクセル値を必要とするフィルタを行う方法です。 – Taro

+0

いいえ、フィルタではありません。液体シミュレータ(Stamによる)からの線形方程式ソルバーです。私の目標は、コードをGPUコードに変更することです。しかし、あなたの提案は正しいかもしれません...私は入力データをコピーする必要がありますし、それは...それはまだ私が推測するパラレルです。私はそれをCPUバージョンのように順次作成する必要があります。 – frankozx

答えて

1

上記のコメントは、純粋な順次実装であっても、データをコピーする必要があります。あなたのhardareに合ったどんな値で打ち上げ境界を置き換える

update<<<dim3(16, 16), dim3(64, 64)>>>(input, output, width, height); 

使用して、

__global__ void update(...) 
    for(int i = threadIdx.x + blockDim.x * blockIdx.x; i <= N; i += blockDim.x * gridDim.x) 
{ 
    for(int j = threadIdx.y + blockDim.y * blockIdx.y; j <= N; j += blockDim.y * gridDim.y) 
    { 
     output[i,j] = update_func(input, i, j); 
    } 
} 

あなたは(ホストから)呼び出すことができます。ここで(メモリ管理コードまたは任意のさらなる詳細なし)カーネルかもしれません

+0

Regis Portalez私の要点は、カーネルの標準for-loopsの使用を避けることでしたが、不可能な場合はCPUのバージョンよりも遅くはありませんか? – frankozx

+0

あなたは配列サイズが十分に小さく、スレッドグリッドが十分に大きいことを避けることができます。 threads *ブロックよりも多くの行がある場合は、forループが必要です。 あなたのコードを考えると、CPUにデータをあまりにも頻繁に戻さない限り、GPU上ではるかに高速になると言えます。しかし、あなたができることは、正確な答えを得るために実際のコードを実行することです。 –

+0

多分この[リンク](http://stackoverflow.com/questions/11994679/solving-2d-diffusion-heat-equation-with-cuda) –