c++ - 使用 CUDA 计算二维像素阵列,声明适当的网格和 block 大小

标签 c++ c arrays opengl cuda

我正在使用 CUDA 计算已展平的 64x64x4 数组的值。该数组包含 GLubytes,然后在 z 列中存储任何给定像素的 RGBA 值。我已经创建了一个与 CUDA 一起使用的内核,但我认为我的 block 和网格的尺寸是关闭的。最终结果不是画圆,我只画了四分之一的圆。调用的内核和函数如下:

澄清一下:DIAMETER = 64,RADIUS = 32。

__global__ void drawKernel(GLubyte *ball)
{
    int x = (blockIdx.x * blockDim.x) + threadIdx.x;
    int y = (blockIdx.y * blockDim.y) + threadIdx.y;


    ball[4 * (x * DIAMETER + y)+3] = (GLubyte) 0x0;  
    if ((x * x) + (y * y) <= (RADIUS * RADIUS)){ 
        ball[4 * ((x+32) * DIAMETER + (y+32))+0] = (GLubyte) 0xffffff;  
        ball[4 * ((x+32) * DIAMETER + (y+32))+1] = (GLubyte) 0x0; 
        ball[4 * ((x+32) * DIAMETER + (y+32))+2] = (GLubyte) 0x0; 
        ball[4 * ((x+32) * DIAMETER + (y+32))+3] = (GLubyte) 0xaaaaaa;
    }
}

cudaError_t drawWithCuda()
{
    size_t memorySize = DIAMETER * DIAMETER * 4 *sizeof(GLubyte);
    GLubyte *dev_ball = 0; //device ball
    cudaError_t cudaStatus; //CUDA error status
    dim3 threadsPerBlock(8, 8);
    dim3 numBlocks(DIAMETER/threadsPerBlock.x, DIAMETER/threadsPerBlock.y);

    // Choose which GPU to run on, change this on a multi-GPU system.
    cudaStatus = cudaSetDevice(0);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaSetDevice(0) failed! CUDA-capable GPU not on board.");
        goto Error;
    }

    // Allocate GPU buffers for GLubyte array 
    cudaStatus = cudaMalloc((void**)&dev_ball, memorySize);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    //Begin CUDA-kernal call

    drawKernel<<<numBlocks, threadsPerBlock>>>(dev_ball);

    cudaDeviceSynchronize();

    //Copy from Device
    cudaStatus = cudaMemcpy(ball, dev_ball, memorySize, cudaMemcpyDeviceToHost);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "Device to Host failed!");
        goto Error;
    }

    Error:
        cudaFree(dev_ball);

    return cudaStatus;
}

我的问题是:我的问题是否存在于我的 Block 和 Grid 的维度中?还是其他原因?

输出(一旦我通过 openGL 运行 arrray ball)如下图: enter image description here

我应该补充一点,当我不使用 cuda 而只是用常规的 for 循环计算数组值时,内核内部使用的逻辑运行得非常好并画出圆圈。

最佳答案

您正在分配这么多内存(在 ball 中):

    size_t memorySize = DIAMETER * DIAMETER * 4 *sizeof(GLubyte);

即一个 64 x 64 x 4 字节深的数组

现在让我们看看内核中的数组索引计算:

    ball[4 * ((x+32) * DIAMETER + (y+32))+0] = (GLubyte) 0xffffff; 

您的xy 计算如下:

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

鉴于您的内核启动尺寸,您正在启动 DIAMETER x DIAMETER 线程阵列,即 64x64。因此,每个 x 都在 0 到 63 之间变化,每个 y 都在 0 到 63 之间变化,具体取决于线程。

当我们将其中一些 xy 值插入您的内核时,索引计算会爆炸(超出分配的内存):

    ball[4 * ((63+32) * 64 + (63+32))+0] = (GLubyte) 0xffffff; 

这超出了 ball 中 64x64x4 的可用区域。如果您使用 cuda-memcheck 运行此代码,我敢肯定您会看到越界索引错误。

看起来你的数组索引应该是这样的:

    ball[4 * ((x) * DIAMETER + (y))+0] = (GLubyte) 0xffffff; 

关于c++ - 使用 CUDA 计算二维像素阵列,声明适当的网格和 block 大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20166520/

相关文章:

JavaScript 数组包含值之一

c++ - 在没有 std::function 的情况下将 lambdas/函数存储在 std::vector 中

c++ - 检查数组中的总和是否可能

使用 libtomcrypt 计算 websocket Sec-WebSocket-Accept 值

c - 在调用 mmap 后是否需要保持文件打开状态?

c - Variadic 宏预期在数字常量之前为 ')'

c++ - 使用引用遍历链表不起作用

c++ - 用 C++ 设计一个 ipstack

ios - cellForRowAtIndexPath Swift 中的多维数组循环

c++ - 堆栈数组 C++ 的 Strcpy 行为