2010-10-01 85 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并访问每个第四个字节。