2014-02-10 238 views
1
for (int ir = 0; ir < nr; ir++) 
{ 
    td = 0; 
    md = 0; 
    for (int i = 0; i < nc; i++) 
    { 
     d[ir * nc + i] = func(nc, cH, vH, ir, i); 
     td   += dist[ir * nc + i]; 
    } 

    md  = td/nc; 
    mdi[ir] = md; 
} 

我有上面的代碼,我想將它移植到GPU。我試過這段代碼;移植到Cuda

//get thread IDs 
const int ir = blockDim.y * blockIdx.y + threadIdx.y; //nR 
const int i = blockDim.x * blockIdx.x + threadIdx.x; //nC 
int  td = 0; 
int  md = 0; 

d[ir * nc + i] = func(nc, c, v, ir, i); //out 
td   += d[ir * nc + i]; 

md = td/nc; 
if (i % nc == 0) 
{ 
    mdi[ir] = md;//out 
    td  = 0; 
    md  = 0; 
} 

但是結果不符。我究竟做錯了什麼?有什麼建議?

+7

請提供完整,compi這兩種情況的標籤代碼。指出你期望的結果和你實際得到的結果。 –

+1

一個問題是'td + ='。在串行版本中,您在內部循環中更新它,這意味着循環中的迭代之間存在依賴關係。並行化時必須重構這些依賴關係。它看起來像你試圖做到這一點,但你創建一個線程本地'td'變量,然後你只添加一次。也就是說,變量不會被每個線程更新。這個特定問題的一個選擇是使'td'變量爲全局變量,並用'atomicAdd()'對其進行更新。儘管如此,這可能並不理想。 –

+1

您可以在標題和正文中添加一些內容來描述您要移植的算法類型?原因是SO上的問題應該比OP更有利於他人。僅對OP有益的問題太局部化了。如問題所述,問題僅對您有益,因爲無法移植相同類型的算法的用戶無法在搜索中找到該問題。 –

回答

1

第二個代碼是不完整的:我不能看到的Çv的定義和在第二代碼我不能看到DIST陣列。

假設沒有錯誤,我可以看到一個大問題。 在我看來,你正在填充一個2D矩陣func(...),沒關係。

當您嘗試填充一維矢量時出現問題。 md它不是一個共享變量,因此寫入數組的值將對應於寫入線程計算的值。

如果你的問題是足夠小,你應該讓TD塊中的一個共同的價值: How to share a common value between threads in a given block?

記得寫之前,該塊中的線程同步: CUDA: synchronizing threads

如果NC大於塊大小比你應該減少你的矩陣的每一行http://developer.download.nvidia.com/compute/cuda/1.1-Beta/x86_website/projects/reduction/doc/reduction.pdf