2016-09-26 5 views
-3

addAtomicが期待したとおりに動作しない状況があります。私はcudaにはとても新しいので、何かが欠けている可能性が高いですが、この日はほぼ確実にこの日に立ち往生し、プログラムの他のほとんどの領域をメモリ割り当ての問題と見なして書き直しました。しかし、これはそうではないようです。uda、addAtomicが奇妙な結果を生成する

実際に起こっていることは、データの最小/最大と合計値を生成する必要のある '分析'カーネルを呼び出すことです。同じデータが合計としてmin/maxに使用されます。しかし、atomicadd演算の結果は、メモリアドレスのように読み取られます。非常に非常に大きな数字。私が逃しているものがありますか?私はこれを100回以上行って、min/maxとsumを除いてカーネルからほとんどすべてを取り除きました。

__global__ void analyze(int *data, int *min, int *max, int *mean) 
{ 
    int t_id = (threadIdx.x * AXIS_COUNT) + blockIdx.x; 
    int b_id = blockIdx.x; 

    int localVal = data[t_id]; 
    atomicMin(&min[b_id], localVal); 
    atomicMax(&max[b_id], localVal); 
    atomicAdd(&mean[b_id], localVal); 
} 
    ........... 
    int r; 
    int step = WINDOW_LENGTH * AXIS_COUNT; 
    for (r = 0; r < out_rows; r++){ 
     analyze<<<AXIS_COUNT, WINDOW_LENGTH>>>(
               &d_data[r * step], 
               &d_min[r * AXIS_COUNT], 
               &d_max[r * AXIS_COUNT], 
               &d_mean[r * AXIS_COUNT]); 
    } 

    cudaDeviceSynchronize(); 

    cudaMemcpy(h_min, d_min, int_size, cudaMemcpyDeviceToHost); 
    cudaMemcpy(h_max, d_max, int_size, cudaMemcpyDeviceToHost); 
    cudaMemcpy(h_mean, d_mean, int_size, cudaMemcpyDeviceToHost); 
    for(r=0; r < out_rows; r++) { 
     fprintf(stderr, "mean %d, x: %d, y: %d z: %d\n", r, h_mean[r*AXIS_COUNT], h_mean[r*AXIS_COUNT + 1], h_mean[r*AXIS_COUNT+2]); 
    } 

結果が形をしている:

mean 5025, x: 2078310793, y: 1999653847 z: -1453684997 
mean 5026, x: 2078308025, y: 1999646363 z: -1453660854 
mean 5027, x: 2078305391, y: 1999639383 z: -1453636904 
mean 5028, x: 2078304342, y: 1999630356 z: -1453613212 

私が検証し、確認するために、関連書類を最小/最大値をチェックしています。

+0

CUDAは** not ** C! – Olaf

+2

'd_mean'をゼロに初期化する部分を表示していません。 [最小限の、完全で検証可能な例](http://stackoverflow.com/help/mcve)を投稿してください。 – tera

+0

@tera:これは根本的な原因だと確信していますが、誰が知っていますか? – talonmies

答えて

-3

答えは、カーネル内の共有メモリを初期化することでした。

__shared__ double sum[AXIS_COUNT]; 
    if (threadIdx.x == 0) { 
     int i; 
     for (i=0; i < AXIS_COUNT; i++) 
      sum[i] = 0; 
    } 


    syncthreads(); 
    int t_id = (threadIdx.x * AXIS_COUNT) + blockIdx.x; 
    int b_id = blockIdx.x; 
+1

あなたの質問にあるカーネルには共有メモリの使用がありませんでした。だから、どのように共有メモリを初期化すると何が変わるでしょうか? – talonmies