对网格和块尺寸的混淆

时间:2013-06-13 11:29:19

标签: cuda

我试图在Udacity课程的第一课结束时解决问题,但我不确定我是否只是犯了一个愚蠢的错误或实际代码是错误的。

void your_rgba_to_greyscale(const uchar4 * const h_rgbaImage, uchar4 * const d_rgbaImage, unsigned char* const d_greyImage, size_t numRows, size_t numCols)
{
    size_t totalPixels = numRows * numCols;
    size_t gridRows = totalPixels / 32;
    size_t gridCols = totalPixels / 32;
    const dim3 blockSize(32,32,1);
    const dim3 gridSize(gridCols,gridRows,1);
    rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage, d_greyImage, numRows, numCols);
    cudaDeviceSynchronize(); checkCudaErrors(cudaGetLastError());
}

另一种方法是:

void rgba_to_greyscale(const uchar4* const rgbaImage, unsigned char* const greyImage, int numRows, int numCols)
{   
    int x = (blockIdx.x * blockDim.x) + threadIdx.x;
    int y = (blockIdx.y * blockDim.y) + threadIdx.y;
    uchar4 rgba = rgbaImage[x * numCols + y];
    float channelSum = 0.299f * rgba.x + 0.587f * rgba.y + 0.114f * rgba.z;
    greyImage[x * numCols + y] = channelSum;
}

错误消息说明如下: libdc1394错误:无法初始化libdc1394 在student_func.cu:76的Cuda错误 未指定的启动失败cudaGetLastError() 我们无法执行您的代码。您是否正确设置了网格和/或块大小?

您的代码已编译! 错误输出:libdc1394错误:无法初始化libdc1394 在student_func.cu:76的Cuda错误 未指定的启动失败cudaGetLastError()

第76行是第一个代码块中的最后一行,据我所知,我没有改变其中的任何内容。我实际上找不到cudaGetLastError()的声明。

我主要关注我对设置网格/块尺寸的理解+关于像素位置的一维数组与我的线程之间的映射是否正确的第一种方法方法。

修改 我想我误解了一些事情。 numRows =垂直方向的像素数? numCols =水平方向的像素?我的块由8 x 8个线程组成,每个线程代表1个像素?如果是这样,我假设这就是为什么我在计算gridRows时必须除以4,因为图像不是正方形?我假设我也可以制作一个2:1列的行:行?

Screen shot

编辑2: 我只是试图改变我的块,使其比例为2:1,所以我可以将numRows和numCol除以相同的数字,但它现在在底部和侧面显示空白区域。为什么底部和侧面都有空白区域。我没有改变网格或块的y维度。

enter image description here

1 个答案:

答案 0 :(得分:9)

每个块处理32 * 32像素,并且有(totalPixels / 32)*(totalPixels / 32)块,所以你处理totalPixels ^ 2像素 - 这似乎是错误的

第1次错了,这应该是正确的:

const dim3 blockSize(32,32,1);

size_t gridCols = (numCols + blockSize.x - 1) / blockSize.x;
size_t gridRows = (numRows + blockSize.y - 1) / blockSize.y;

这是2d非常常见的模式 - 你可以记住它

样本中的

图像大小不是2的幂,你想要块来覆盖你的所有图像(甚至更多)

所以下一步必须正确: gridCols * blockSize.x&gt; = numCols gridRows * blockSize.y&gt; = numRows

您选择块大小并以此为基础计算覆盖所有图像所需的块数量

之后,在内核中,对于尺寸不佳的情况,你必须检查你是不是“没有图像”

另一个问题是在内核中,它必须是(y * numCols + x),而不是oposite

内核:

int x = (blockIdx.x * blockDim.x) + threadIdx.x;
int y = (blockIdx.y * blockDim.y) + threadIdx.y;

if(x < numCols && y < numRows)
{
    uchar4 rgba = rgbaImage[y * numCols + x];
    float channelSum = 0.299f * rgba.x + 0.587f * rgba.y + 0.114f * rgba.z;
    greyImage[y * numCols + x] = channelSum;
}

调用代码:

const dim3 blockSize(4,32,1); // may be any

size_t gridCols = (numCols + blockSize.x - 1) / blockSize.x;
size_t gridRows = (numRows + blockSize.y - 1) / blockSize.y;

const dim3 gridSize(gridCols,gridRows,1);
rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage, d_greyImage, numRows, numCols);
cudaDeviceSynchronize(); 
checkCudaErrors(cudaGetLastError());
该死的,我觉得我做的事情更难理解(