我正在使用 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)如下图:
我应该补充一点,当我不使用 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;
您的x
和y
计算如下:
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 之间变化,具体取决于线程。
当我们将其中一些 x
和 y
值插入您的内核时,索引计算会爆炸(超出分配的内存):
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/