2012-01-05 9 views
3

forループ内でカーネルを繰り返し呼び出すCUDAプログラムがあります。 コードは、行列全体が完了するまで前の式で計算された値を使用して、行列のすべての行を計算します。 これは基本的に動的プログラミングアルゴリズムです。 以下のコードは、カーネルの と並行して、多くの別個の行列の(i、j)エントリを塗りつぶします。forループ内でカーネルを繰り返し呼び出すCUDAプログラムでパフォーマンスが低下する

for(i = 1; i <=xdim; i++){ 

    for(j = 1; j <= ydim; j++){ 

    start3time = clock(); 
    assign5<<<BLOCKS, THREADS>>>(Z, i, j, x, y, z) 
    end3time = clock(); 
    diff = static_cast<double>(end3time-start3time)/(CLOCKS_PER_SEC/1000); 
    printf("Time for i=%d j=%d is %f\n", i, j, diff); 
    } 

} 

カーネルassign5は私の問題は、私はこのプログラムを実行すると、各iとjのための時間が 時間の0ほとんどですが、時にはそれが10ミリ秒であるということである

__global__ void assign5(float* Z, int i, int j, int x, int y, int z) { 

    int id = threadIdx.x + blockIdx.x * blockDim.x; 

    char ch = database[j + id]; 

    Z[i+id] = (Z[x+id] + Z[y+id] + Z[z+id])*dev_matrix[i][index[ch - 'A']]; 

    } 

} 

簡単です。出力は次のようになります

Time for i=0 j=0 is 0 
Time for i=0 j=1 is 0 
. 
. 
Time for i=15 j=21 is 10 
Time for i=15 j=22 is 0 
. 

私はこれがなぜ起こっているのか分かりません。スレッドの競合状態が表示されません。私は右のiとjについて、最初のループ時間後

if(i % 20 == 0) cudaThreadSynchronize(); 

を追加する場合、ほとんど0です。しかし、その後の同期のための時間 は時々10あるかさえ20 CUDAがで多くの操作 を実行しているように思えます低コストであり、その後の費用が高い。どんな助けもありがとう。

+3

確かに時間ソースの精度が低すぎるため、これは単なるエイリアシングです。 – talonmies

+0

変数Zとデータベースがデバイスのグローバル配列、dev_matrix、インデックスとデバイスの定数配列であることを追加するのを忘れました。メモリアクセスが統合されます。 – Ross

+4

時計の解像度が約10msなので、結果は矛盾しています。ループ全体の時間を測定するほうが簡単です。高解像度、反復測定が必要な場合は、[この回答](http://stackoverflow.com/a/588377/324625)を参考にしてください。 –

答えて

6

CUDAのカーネルコールがホスト上で実際に何をしているのか誤解していると思います。カーネルコールは非ブロッキングで、デバイスのキューにのみ追加されます。カーネルコールの前後で時間を測定している場合、その違いはカーネルコールの時間(カーネルコールをキューに追加する時間を測定する)とは関係ありません。

カーネルコールごとにの後に、そしてend3timeを測定する前にcudaThreadSynchronize()を追加する必要があります。 cudaThreadSynchronize()は、キュー内のすべてのカーネルが作業を終了した場合にそれをブロックして返します。

if(i % 20 == 0) cudaThreadSynchronize(); 

があなたのmeasurmentsでスパイクを作っ理由。これは、

+1

ありがとうございます、これは今や理にかなっています。また、cudaMemcpyはすべてのスレッドが終了するまでブロックされます。 – Ross

+1

はい、すべてのスレッドが終了するまで、ホスト上のcudaMemcpyブロックを呼び出します。これは標準的なmemcopy関数なので、ほとんどの場合、必要なものです。非ブロッキングバリアントであるcudaMemcpyAsync()もあります。 – shapecatcher

+1

将来の読者のためのリファレンスとして:cudaThreadSyncronizeは推奨されず、代わりにcudaDeviceSynchronizeを使用する必要があります。 – AkiRoss

関連する問題