2012-07-30 41 views
0

我想了解CUDA編程模型及其features.As練習,我想下面的循環結構,函數調用轉換成有效的CUDA內核CUDA內核原子能產生錯誤的答案

//function call 
bool gmul(int rowsize,int *Ai,int *Bj,int colsize) 
{ 
    for(int i = 0;i < rowsize;i++) 
    { 
     for(int j = 0;j < colsize;j++) 
     { 
      if(Ai[i] == Bj[j]) 
      { 
       return true; 
      } 
     } 
    } 
    return false; 
} 

//Some for loop in main function is as follows 

for(i = 0;i < q ;i++) 
    { 
     cbeg = Bjc[i]; 
     cend = Bjc[i+1];   
     for(j = 0;j < m;j++) 
     { 
      beg = Aptr[j]; 
      end = Aptr[j+1];    
      if(gmul(end - beg,Acol + beg,Bir + cbeg,cend - cbeg)) 
      { 
       temp++;    
      }      
     } 
     Cjc1[i+1] = temp ;    
    } 

而我的函數調用的內核如下。

__device__ bool mult(int colsize,int rowsize,int *Aj,int *Bi,int *val) 
    {  
     for(int j = 0; j < rowsize;j++) 
     {   
      for(int k = 0;k < colsize;k++) 
      { 
       if(Aj[j] == Bi[k]) 
       {  
       return true; 
       }        
      }   
     } 
      return false;  
    } 


__global__ void kernel(int *Aptr,int *Aj,int *Bptr,int *Bi,int rows,int cols,int *count,int *Cjc) 
    { 
     int tid = threadIdx.x + blockIdx.x * blockDim.x; 
     int i; 
     if(tid < cols) 
     { 
      int beg = Bptr[tid]; 
      int end = Bptr[tid+1]; 
      for(i = 0;i < rows;i++) 
      { 
       int cbeg = Aptr[i]; 
       int cend = Aptr[i+1]; 
       if(mult(end - beg,cend - cbeg,Aj+cbeg,Bi+beg,count)) 
       { 
        //atomicAdd(count,1); 
            //Changes made are in next line 
           atomicAdd(Cjc+tid+1,1);   
       } 
      } 
      //atomicAdd(Cjc+tid+1,*count);    
     }    
    } 

我要的是,每當__device__ multtrue返回值,我的全球核函數應該增加計數器針對特定線程,一旦for循環(內核功能)結束,它應該值存儲到​​數組和計數被交給其他線程進行增量操作。但是,我沒有得到預期的價值。所有我在這個​​陣列中得到的數據是所有線程完成執行後的最終計數。

我使用GTX 480 CC 2.0

任何建議/提示,爲什麼我會得到錯誤的答案或優化這個CUDA內核將不勝感激。 在此先感謝。 * ** * ****解決* ** * ** * ****

現在,我面臨的一個問題,每當我達到4000及以上的大小時,我將得到數組中所有元素的值爲0。這是我如何啓動內核。

int numBlocks,numThreads; 

     if(q % 32 == 0) 
     { 
      numBlocks = q/32; 
      numThreads = 32; 
     } 
     else 
     { 
      numBlocks = (q+31)/32; 
      numThreads = 32; 
     } 
findkernel<<<numBlocks,numThreads>>>(devAptr,devAcol,devBjc,devBir,m,q,d_Cjc);   

我想知道我穿越塊或網格尺寸的任何限制,但對於CC 2.0,我覺得我恰到好處地推出足夠的塊和線程不跨越任何限制。我想知道爲什麼仍然所有的答案都以0出現。

+1

你的第一步應該是谷歌的「平行前綴總和」或「掃描」。這將爲實現這種累加求和提供一些合理的算法基礎。現在已經有許多優秀的CUDA實現可供您查看,以瞭解如何正確實施它。 – talonmies 2012-07-30 05:51:24

+0

@ talonmies..Thanks ...我會嘗試將個別計數存儲在一個數組中,然後我會嘗試實現並行前綴總和或掃描...我想知道推力是否有相同的執行... – Recker 2012-07-30 06:18:59

+0

'thrust :: exclusive_scan'或'thrust: :inclusive_scan'可能是你正在尋找的。 – talonmies 2012-07-30 07:35:06

回答

1

您已經編寫了並行線程,可以在沒有同步的情況下讀寫count。線程以不可預知的順序併發運行,所以線程以不可預知的順序原子地修改count並讀取count。根據確切的執行順序,表達式*count將產生不同的結果。

一次for循環(在覈函數)結束,它應的值存儲到​​陣列和計數被移交給其他線程增量操作。

沒有同步,所以沒有線程等待另一個線程完成循環。爲什麼不給每個線程分配不同的存儲空間,而不是讓所有線程共享同一個存儲空間count?然後線程不會影響彼此的結果。您可以在此之後運行掃描內核來合併結果。

+0

@Heatsink ....謝謝...我會嘗試把每個計數的結果放在一個數組中,然後我會嘗試應用並行前綴和或掃描它。 – Recker 2012-07-30 06:14:06