0

LinuxシステムとTeslaC2075マシンで動作しています。リダクションカーネルの修正バージョンであるカーネルを起動しています。私の目的は、大規模なデータセット(結果)の平均と段階的な平均バージョン(time_avg)を見つけることです。以下のコードを参照してください。

「result」と「time_avg」のサイズは同じで、「nsamps」と同じです。「time_avg」には、配列結果の連続した平均セットが含まれます。したがって、前半には2つの重複しないサンプルごとの平均が含まれ、その後の四半期には4つの重複しないサンプルごとの平均が含まれ、次の8分の1は8つのサンプルごとに含まれます。

__global__ void timeavg_mean(float *result, unsigned int *nsamps, float *time_avg, float *mean) {

__shared__ float temp[1024];
int ltid = threadIdx.x, gtid = blockIdx.x*blockDim.x + threadIdx.x, stride;
int start = 0, index;
unsigned int npts = *nsamps;

printf("here here\n");

// Store chunk of memory=2*blockDim.x (which is to be reduced) into shared memory
if ( (2*gtid) < npts ){
        temp[2*ltid] = result[2*gtid];
        temp[2*ltid+1] = result[2*gtid + 1]; 
}    
        for (stride=1; stride<blockDim.x; stride>>=1) {
                __syncthreads();
                if (ltid % (stride*2) == 0){ 
                  if ( (2*gtid) < npts ){
                        temp[2*ltid] += temp[2*ltid + stride];
                        index = (int)(start + gtid/stride);
                        time_avg[index] = (float)( temp[2*ltid]/(2.0*stride) );
                  }   
                }   
        start += npts/(2*stride);
        }   
__syncthreads();
if (ltid == 0)
{
        atomicAdd(mean, temp[0]);    
}
__syncthreads();
printf("%f\n", *mean);
}

起動構成は40ブロック、512スレッドです。データセットは約40kサンプルです。

私のメインコードではcudaGetLastError()、カーネル呼び出しの後に呼び出しますが、エラーは返されません。メモリ割り当てとメモリコピーはエラーを返しません。カーネル呼び出しの後に書くcudaDeviceSynchronize()(またはcudaMemcpy平均値をチェックする)と、カーネル呼び出しの後でプログラムが完全にハングします。削除すると、プログラムが実行されて終了します。どちらの場合も、「ここに」出力または平均値が出力されますか。カーネルが正常に実行されない限り、printfは印刷されないことを理解しています。これは__syncthreads()再帰と関係がありますか?すべてのスレッドが同じ深さまで進むので、チェックアウトすると思います。

ここでの問題は何ですか?

ありがとうございました!

4

2 に答える 2

4

カーネル呼び出しは非同期です。カーネルが正常に起動した場合、ホストコードは引き続き実行され、エラーは表示されません。カーネルの実行中に発生するエラーは、明示的な同期を実行するか、暗黙的な同期を引き起こす関数を呼び出した後にのみ表示されます。
ホストがカーネルの実行を終了していない可能性があるよりも同期でハングしている場合は、無限ループを実行している__synchthreads()か、他の同期プリミティブを待機しています。
コードに無限ループが含まれているようです:for (stride=1; stride<blockDim.x; stride>>=1)。あなたはおそらくストライドを右ではなく左にシフトしたいと思うでしょう:stride<<=1

再帰について言及しましたが、コードには__global__関数が1つしか含まれておらず、再帰呼び出しはありません。

于 2013-03-24T13:39:42.377 に答える
1

カーネルには無限ループがあります。forループを次のように置き換えます

for (stride=1; stride<blockDim.x; stride<<=1) {
于 2013-03-24T13:51:41.707 に答える