2011-03-11 579 views
4

我試圖開發一個小CUDA程序找指定的數組中的最大值,CUDA找到最大值在給定的數組

int input_data[0...50] = 1,2,3,4,5....,50 

max_valueinput_data[0], 最終的答案的第一個值初始化存儲在result[0]。 內核給出0作爲最大值。我不知道問題是什麼。 我執行1塊50線程。

__device__ int lock=0; 

__global__ void max(float *input_data,float *result) 
{ 
    float max_value = input_data[0]; 
    int tid = threadIdx.x; 

    if(input_data[tid] > max_value) 
    { 
     do{} while(atomicCAS(&lock,0,1)); 
     max_value=input_data[tid]; 
     __threadfence(); 
     lock=0; 
     } 

    __syncthreads(); 
    result[0]=max_value; //Final result of max value 
} 

即使有內置功能,只是我正在練習小問題。

回答

4

您正在嘗試設置「關鍵部分」,但CUDA上的這種方法會導致整個程序掛起 - 儘量避免它。

爲什麼你的代碼掛起?

內核(__global__功能)是由32個線程組執行,稱爲翹曲。單個warp內的所有線程同步執行。所以,經線將停止在你的do{} while(atomicCAS(&lock,0,1))之前,直到全部從你的經線中取得鎖的成功。但顯然,您想要防止多個線程同時執行關鍵部分。這導致掛起。

替代解決方案

你需要的是一個 「平行減少算法」。你可以開始閱讀這裏:

+0

好的。即使需要很長時間來執行我也不會回答。如果每個花紋獲得其鎖定,則必須更新max_value,但不更新。如何解決 – kar 2011-03-11 08:07:59

+0

你可以使用atomicMax。由於我已經解釋過的原因,你現在所做的關鍵部分顯然不會工作。 – CygnusX1 2011-03-11 15:11:59

1

你的代碼有潛在的競爭。我不確定您是否在共享內存中定義了「max_value」變量,但都是錯誤的。 1)如果'max_value'只是一個局部變量,那麼每個線程保存它的本地拷貝,它不是實際的最大值(它們只是input_data [0]和input_data [tid]之間的最大值) )。在最後一行代碼中,所有線程都將結果[0]寫入自己的max_value,這會導致未定義的行爲。 2)如果'max_value'是一個共享變量,49個線程將進入if語句塊,並且他們將嘗試使用鎖一次更新'max_value'。但是49個線程之間的執行順序沒有定義,因此有些線程可能會將實際的最大值覆蓋爲較小的值。您需要在臨界區域內再次比較最大值。

1

Max是一種「減少」 - 檢查SDK中的縮減示例,並執行最大值而不是總和。

白皮書有點老,但仍然相當有用:

http://developer.download.nvidia.com/compute/cuda/1_1/Website/projects/reduction/doc/reduction.pdf

最後的優化步驟是使用「經同步」的編碼,以避免不必要的__syncthreads()調用。

它至少需要2內核調用 - 一個寫一堆中間最大的()值到全局存儲器,然後另取該陣列的最大()。

如果你想這樣做在一個單一的內核調用,檢查出threadfenceReduction SDK樣本。它使用__threadfence()和atomicAdd()跟蹤進度,然後當所有塊完成中間結果的寫入後,有1個塊會最終減少。

-1

對變量有不同的訪問。當您通過設備那麼變量放在GPU全局內存定義一個變量,它是由在網格中的所有線程訪問,共享地方塊共享內存中的變量,這只是該塊的線程訪問,在最後,如果你不使用像浮動MAX_VALUE那麼任何關鍵字的變量被放置在線程寄存器,它可以訪問僅在thread.In代碼每個線程有局部變量MAX_VALUE,它不識別其他線程中的變量。

相關問題