2010-10-01 84 views
1

我正嘗試在GPU上使用共享內存將256x256數據陣列與濾波器進行卷積,3x3。我知道我要將這個數組分塊,然後在每個模塊中應用這個過濾器。這最終意味着沿着邊緣重疊的塊和一些填充將需要在沒有數據的邊緣周圍進行,以便過濾器正常工作。在CUDA中使用濾波器進行卷積,陣列

int grid = (256/(16+3-1))*(256/(16+3-1)) 其中256是我的陣列的長度或寬度,圖16是在共享存儲器中的我的塊的長度或寬,3是我的過濾器的長度或寬度,並且我減一,使之所以它甚至。

int thread = (16+3-1)*(16+3-1)

現在我把我的內核< < >>(輸出,輸入,256) 輸入和輸出大小爲256的數組* 256

__global__ void kernel(float *input, float *output, int size) 
{ 
    __shared__ float tile[16+3-1][16+3-1]; 
    blockIdx.x = bIdx; 
    blockIdy.y = bIdy; 
    threadIdx.x = tIdx; 
    threadIdy.y = tIdy 

    //i is for input 
    unsigned int iX = bIdx * 3 + tIdx; 
    unsigned int iY = bIdy * 3 + tIdy; 

    if (tIdx == 0 || tIdx == width || tIdy == 0 || tIdy == height) 
    { 
     //this will pad the outside edges 
     block[tIdy][tIdx] = 0; 
    } 
    else 
    { 
     //This will fill in the block with real data 
     unsigned int iin = iY * size + iX; 
     block[tIdy][tIdx] = idata[iin]; 
    } 

    __syncthreads(); 

    //I believe is above is correct; below, where I do the convolution, I feel is wrong 
    float result = 0; 
    for(int fX=-N/2; fX<=N/2; fX++){ 
     for(int fY=-N/2; fY<=N/2; fY++){ 
      if(iY+fX>=0 && iY+fX<size && iX+fY>=0 && iX+fY<size) 
       result+=tile[tIdx+fX][tIdy+fY]; 
     } 
    } 
    output[iY*size+iX] = result/(3*3); 
} 

當我運行代碼,如果我運行卷積部分,會出現內核錯誤。任何見解?還是建議?

+0

根據您擁有的GPU和您試圖運行共享內存分配的線程數可能太大。您可能需要重新考慮實施,因爲您無法運行具有如此大規模分配的許多線程。 – 2010-10-01 18:30:01

+0

CUDA SDK有幾個卷積的例子。您可能想與之比較,看看您的實現有何不同。 CUFFT庫也是另一種可能性。 – peakxu 2011-03-01 18:19:21

回答

3

查看sobelFilter SDK示例。

它使用紋理來處理邊緣情況,稍微過度取塊(但紋理緩存使效率更高),並使用共享內存進行處理。

關於共享內存的微妙之處在於,如果您讀取相鄰的字節,您會遇到4路銀行衝突。解決這個問題的一種方法,如sobelFilter示例所示,是展開循環4x並訪問每個第四個字節。