0

CUDAに複雑なアルゴリズムを実装しています。しかし、本当に奇妙な問題があります。問題は次のように要約できます。カーネルは一連の計算を何度も繰り返します。現在の反復の計算は、前の反復の結果に基づいています。各反復でブロック間で情報を渡すために、グローバルメモリ上の配列を使用しています。たとえば、2つのブロックがあり、反復ごとにブロック0が結果をグローバルメモリに保存し、ブロック1がグローバルメモリから結果を読み取ります。ただし、問題は、ブロック1がグローバルメモリから配列を読み取れないことです。前の反復ではなく、最初の反復の結果を返す場合があります。

a_eとe_aはグローバルメモリ上の2つの配列であり、サイズは[2*8]です。d_a_eとd_e_aは共有メモリ上にあり、サイズは[blockDim.x +1][8]です。

if(threadIdx.x<8)
{
     //block 0 writes, block 1 reads, this can't work properly
     a_e[blockIdx.x*8+threadIdx.x]=d_a_e[blockDim.x][threadIdx.x];
     if(blockIdx.x>0)
          d_a_e[0][threadIdx.x]=a_e[(blockIdx.x-1)*8+threadIdx.x];

     //block 1 writes, block 0 reads, this can work properly
     e_a[blockIdx.x*8+threadIdx.x]=d_e_a[0][threadIdx.x];
     if(blockIdx.x < gridDim.x-1)
          d_e_a[blockDim.x][threadIdx.x]=e_a[(blockIdx.x+1)*8+threadIdx.x];
}
4

1 に答える 1

1

この設定は機能しません。あなたは効果的にあなたのブロックをシリアル化しようとしていますが、彼のコメントでタロンミーがほのめかしているように、それは機能しません。CUDAプログラミングガイドから:

「スレッドブロックは独立して実行する必要があります。並列または直列に任意の順序で実行できる必要があります。この独立性の要件により、スレッドブロックを任意の数のコアにわたって任意の順序でスケジュールできます...」 http:/ /docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#thread-hierarchy

おそらく別のカーネルを起動して(1番目のカーネルでブロック0の計算を実行し、2番目のカーネルでブロック1を実行するなど)、1番目のカーネルからの結果が実行されるように強制する場合の最善の手段は、次のカーネル。ブロック間同期を行うためにいくつかの作業が行われていますが、ブロックをシリアル化する必要があるため、それらから多くのメリットを得ることができません。

編集:ブロックのスケジュールは文書化されておらず、いつでも変更される可能性があるため、ブロック間の同期は移植性がなく、ドライバーまたはCUDAツールキットの更新で中断する可能性があることも指摘しておく必要があります。

于 2013-01-24T00:09:52.747 に答える