CUDA 2d卷积边界不正确

时间:2014-03-26 22:46:50

标签: cuda

我以天真的方式实现了CUDA 2D卷积码,无法正确获得边界值。错误发生在顶部和左侧边框上,滤波器宽度为半个。例如,如果我的滤镜是7x7,则错误位于前3个像素中,并留下3个像素(与C结果相比)。有人可以帮我解决这个错误吗?非常感谢您的帮助!

附上我的cuda代码和c代码:

#define ISIZE 32//input image size ISIZE*ISIZE
#define MASK_RADIUS 3
#define MASK_WIDTH (2 * MASK_RADIUS + 1)
const int FILTER_SIZE = MASK_WIDTH * MASK_WIDTH * sizeof(float);
__device__ __constant__ float d_filter[FILTER_SIZE];

__global__ void convolution2D_cuda(float* d_Result, float* d_Data, int dataH, int dataW)
{
// global mem address for this thread
const int gLoc = threadIdx.x + blockIdx.x * blockDim.x +
                 (threadIdx.y + blockIdx.y * blockDim.y) * dataW; 

float sum = 0;
float value = 0;

for(int i = -MASK_RADIUS; i <= MASK_RADIUS; i++) //row wise
{ 
    for (int j = -MASK_RADIUS; j <= MASK_RADIUS; j++) //col wise
    { 
        // check row 
        if ( (blockIdx.x == 0) && ((threadIdx.x + j) < 0) ) //left apron
            value = 0;
        else if ( blockIdx.x == (gridDim.x -1) && (threadIdx.x + j) > (blockDim.x-1) ) //right apron
            value = 0;          
        else {
            // check col
            if ( blockIdx.y == 0 && (threadIdx.y + i) < 0) //top apron
                value = 0;
            else if ( blockIdx.y == (gridDim.y-1) && (threadIdx.y + i) > (blockDim.y-1) ) //bottom apron
                value = 0;
            else // load data
                value = d_Data[gLoc + i * dataW + j];
        }
        //2d array case: non-separable filter
        sum += value * d_filter[ (MASK_RADIUS - i) * MASK_WIDTH + (MASK_RADIUS - j) ];
    }
}
d_Result[gLoc] = sum;
}

//c code
void convolution2D_cpu(float* result, float* input, float* filter, int dataW, int dataH, int k_Width, int k_Height, int radiusY, int radiusX)
{
      int y, x, ky, kx;
      for (y = 0; y < dataH; y++) { //row
         for (x = 0; x < dataW; x++) {
         result[y*dataW + x] = 0;
         float sum=0;
         for(ky = -radiusY; ky <= radiusY; ky++) {
                 for(kx = -radiusX; kx <= radiusX; kx++) {
                int dy = y + ky;
            int dx = x + kx;
            if (dy >= 0 && dy < dataH) //left & upper borders
                if (dx >= 0 && dx < dataW) //right & lower borders
            sum += input[dy*dataW + dx] * filter[(radiusY-ky)*k_Width + (radiusX - kx)];            
                }
            }
        result[y*dataW+x] = sum;
        }
    }
}



Part of the main() code is :

    dim3 blocks(16, 16);
dim3 grids(width/16, height/16);


    checkCudaErrors( cudaMalloc( (void **)&d_data, data_size ));
checkCudaErrors( cudaMalloc( (void **)&d_result, data_size ));
    checkCudaErrors( cudaMemcpy(d_data, indata, data_size, cudaMemcpyHostToDevice) );
    checkCudaErrors( cudaThreadSynchronize() );

convolution2D_cuda<<<grids, blocks>>>(d_result, d_data, width, height);
    checkCudaErrors( cudaThreadSynchronize() );

    checkCudaErrors( cudaMemcpy(output, d_result, data_size, cudaMemcpyDeviceToHost) );
    checkCudaErrors( cudaThreadSynchronize() );

    //check with result of CPU
    convolution2D_cpu(c_result, indata, filter, width, height, len, len, MASK_RADIUS, MASK_RADIUS);

1 个答案:

答案 0 :(得分:0)

我要解决这个谜团。线程索引计算发生错误。 threadIdx是uint,nvcc认为(threadIdx.x + j)为unsigned int。防爆。如果j为-1,则解释为4294967295(ffffffff),边界索引不正确。