2012-11-22 18 views
0

我正在用CUDA中的原子做一些實驗。我最大的問題是當兩個運行在同一個模塊中的線程原子地訪問相同的地址時,它們的行爲如何。我用atomicAdd嘗試了一些測試,它的工作原理上,但是當我使用atomicCAS嘗試下面的代碼時,結果不是我所期望的。有人有解釋嗎?atomicCAS:塊內的行爲

#include <cuda_runtime.h> 
#include <iostream> 
#include <cuComplex.h> 
using namespace std; 
__global__ void kernel(int * pointer) 
{ 
    *pointer=0; 
    *(pointer+threadIdx.x+1)=0; 
    __syncthreads(); 
    *(pointer+threadIdx.x+1)=atomicCAS(pointer,0,100); 
} 
int main(int argc,char ** argv) 
{ 
    int numThreads=40; 
    dim3 threadsPerBlock; 
    dim3 blocks; 
    int o[numThreads+1]; 
    int * pointer; 
    cudaMalloc(&pointer,sizeof(int)*(numThreads+1)); 
    cudaMemset(pointer,0,sizeof(int)*(numThreads+1)); 
    threadsPerBlock.x=numThreads; 
    threadsPerBlock.y=1; 
    threadsPerBlock.z=1; 
    blocks.x=1; 
    blocks.y=1; 
    blocks.z=1; 
    kernel <<<threadsPerBlock,blocks>>> (pointer); 
    cudaMemcpy(o,pointer,sizeof(int)*(numThreads+1),cudaMemcpyDeviceToHost); 



    for (int i=0;i<numThreads+1;i++) 
      cout << o[i] << " "; 

    cout << endl; 

} 

在同塊訪問中運行相同的地址進行比較上面的代碼atomicCAS和交流......我的期望是,只有一個atomicCAS會發現值進行比較,以0而所有其他人會發現它100,但奇怪的是我的程序的輸出是:

100 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

即所有線程找到的值進行比較,以設置爲0。

回答

5

您已經扭轉的執行配置參數的順序。它是<<<gridDim, blockDim>>>,反之亦然。所以你要啓動40個1線程塊,而不是相反。

這就是爲什麼你會看到結果 - 因爲每個塊中只有一個線程正在運行,所以數組中的最後一個numThreads-1值將始終爲零。

如果我換我得到這個輸出順序:

100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 0 100 100 100 100 100 100 100 

你可以看到,所有的線程,但是一個寫100,並且一個線程寫0,符合市場預期。

+0

Ahh ....是我的愚蠢的錯誤....讓我問一些對我來說非常重要的東西......原子在任何情況下都是原子,或者存在一些他們不工作的特殊情況?我記得在某個地方看了一些東西,但不記得:( – Daniel

2

你的內核調用中有你的線程塊和塊變量。

取而代之的是:

kernel <<<threadsPerBlock,blocks>>> (pointer); 

這樣做:

kernel <<<blocks, threadsPerBlock>>> (pointer); 

然後你會得到正確的輸出。

+1

如果發佈時間沒有那麼不同,我會認爲這是一個同時的答案...... :) – harrism