对网格和块尺寸的混淆

Han*_*del 5 cuda

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

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());
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

我主要关注我对设置网格/块尺寸的理解+第一种方法方法是否适用于一维像素位置和我的线程之间的映射.

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

屏幕截图

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

在此输入图像描述

ShP*_*vel 9

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

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

const dim3 blockSize(32,32,1);

size_t gridCols = (numCols + blockSize.x - 1) / blockSize.x;
size_t gridRows = (numRows + blockSize.y - 1) / blockSize.y;
Run Code Online (Sandbox Code Playgroud)

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

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

所以接下来必须是正确的:gridCols*blockSize.x> = numCols gridRows*blockSize.y> = 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;
}
Run Code Online (Sandbox Code Playgroud)

调用代码:

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());
Run Code Online (Sandbox Code Playgroud)

该死的,我觉得我做的事情更难理解(