2017-03-14 50 views
-1

我試圖與452591個元素執行一個數組的總和減少,它們都設置爲1,所以總和應452591.這個CUDA總和減少有什麼問題?

我計算線程nThreads作爲2下一個功率的數量,所以它是524288.在while循環的每次迭代中,只有第一半的線程應該工作,在第i個元素處增加另一半的值。只有在nvalues上設置的元素數組中的實際值時纔會發生添加。

它適用於127,1025,1072甚至8271個元素。但與452591不同,我可以得到原因。爲452591元的oputput是88064.

__global__ void sum_kernel(int nvalues, double nThreads, double *values) 
{ int i = blockIdx.x * blockDim.x + threadIdx.x; 
    while (nThreads > 1) 
    { int middle = nThreads/2; 
     int j = i + middle; 
     if (i < middle) 
     { if (j < nvalues) 
      { values[i] += values[j]; } 
      else 
      { values[i] += 0; } 
     } 
     __syncthreads(); 
     nThreads = middle; 
    } 
    if (i == 0) 
     printf("T0 ------> %0.f \n", values[0]); 
} 

我的猜測是,有時一些theads加0時,他們不應該...也許我會得到錯誤的線程ID?

對於一些詳情我計算的2下一個功率爲:

int expo = ceil(log(n)/log(base)); 
double next2Pow = (double) pow(base, expo) 

內核被稱爲具有1個暗淡塊和MAX_TPB = 1024爲:

sum_kernel<<< ceil(next2Pow/MAX_TPB), MAX_TPB >>> (nvalues, next2Pow, values_device);

另外,我有檢查並且設備數組中的值是正確的,因爲我可以將它們複製到主機數組中,並在主機中正確獲取總和。

但我想讓內核工作,因爲學習的原因。

+1

我不認爲你理解CUDA執行的本質。 [執行發生在塊](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#scalable-programming-model),所以你減少全局內存不能工作,因爲'__syncthreads ()'只[在一個塊內同步](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#synchronization-functions)。如果你想學習如何編寫一個很好的並行縮減,請嘗試[this](http://developer.download.nvidia.com/assets/cuda/files/reduction.pdf),並且有一個cuda縮減示例代碼與它一起。 –

+0

而不是說上面的「不能工作」,我可能應該說「不能保證正常工作的數據集大小大於2048」 –

+0

@RobertCrovella我想在幻燈片35中的例子,但我得到這個錯誤:沒有實例函數模板「warpReduce」與參數列表參數類型匹配的是:(int [],unsigned int) – user3117891

回答

1

What is wrong with this sum reduction in CUDA?

在CUDA,具有內核啓動(在電網)相關的線程不都步調一致執行在一起。 CUDA execution takes place by blocks

您試圖將整個數據集合減半的方法將取決於網格中的所有線程一起工作。你也可能認爲__syncthreads()同步網格中的所有線程(這將使這成爲可能),但它不會。它只有operates at the block level

而不是進一步剖析這一點,如果你想學習如何編寫CUDA快速並行減少,一個很好的出發點是this treatment of it且有CUDA sample code,提供了一個全面的工作實施涵蓋了各種方法的演示文稿。