CUDA二维卷积边界不正确

CUDA二维卷积边界不正确,cuda,Cuda,我用简单的方法实现了一个CUDA二维卷积码,无法得到正确的边界值。错误发生在过滤器宽度为一半的顶部和左侧边界上。例如,如果我的过滤器是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) con

我用简单的方法实现了一个CUDA二维卷积码,无法得到正确的边界值。错误发生在过滤器宽度为一半的顶部和左侧边界上。例如,如果我的过滤器是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);
#定义ISIZE 32//输入图像大小ISIZE*ISIZE
#定义遮罩半径3
#定义遮罩宽度(2*遮罩半径+1)
常量int FILTER_SIZE=掩码宽度*掩码宽度*大小of(浮点);
__设备uuu uuu常数uuuu浮点d_滤波器[滤波器尺寸];
__全局无效卷积2D_cuda(浮点*d_结果,浮点*d_数据,整数数据H,整数数据W)
{
//此线程的全局mem地址
const int gLoc=threadIdx.x+blockIdx.x*blockDim.x+
(线程IDX.y+块IDX.y*块尺寸y)*dataW;
浮点数和=0;
浮点数=0;
对于(inti=-MASK_RADIUS;i(blockDim.y-1))//下裙板
数值=0;
else//加载数据
值=d_数据[gLoc+i*dataW+j];
}
//二维阵列情况:不可分离滤波器
总和+=值*d_过滤器[(遮罩半径-i)*遮罩宽度+(遮罩半径-j)];
}
}
d_结果[gLoc]=总和;
}
//c代码
无效卷积2D_cpu(浮点*结果、浮点*输入、浮点*过滤器、整数数据W、整数数据H、整数k_宽度、整数k_高度、整数半径Y、整数半径X)
{
int y,x,ky,kx;
对于(y=0;y
我要解开这个谜。错误发生在线程索引计算上。threadIdx是uint,nvcc认为(threadIdx.x+j)是无符号的int.Ex。如果j是-1,则解释为4294967295(ffffffff),边界索引不正确。

您使用的块和网格尺寸是什么?你能给出你调用内核的代码部分吗?一个简单的问题,在CPU部分,你有两个不同的循环,有不同的边界(
radiusY
radiusX
),但在GPU部分,你的循环只有一个边界(
MASK\u RADIUS
),这可能是错误,不是?因为主代码不完整。我不能就此下结论。但是可能会。是的,radiusX和radiusY设置为等于测试的掩码半径。数组的大小
d\u filter[filter\u size]
不正确。这应该是
d\u filter[filter\u SIZE/sizeof(float)]
你的网格有你的图像大小吗?