我正在使用CUDA来计算已被展平的64x64x4数组的值。该数组包含GLubytes,然后在z列中存储任何给定像素的RGBA值。我已经创建了一个与CUDA一起使用的内核,但我认为我的块和网格的尺寸已经关闭。最终的结果是不是绘制圆圈,而是仅绘制四分之一的圆圈。调用的内核和函数如下:
澄清: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球)是下图:
我应该补充一点,当我不使用cuda并且只使用常规for循环计算数组值时,内核中使用的逻辑可以很好地工作并绘制圆圈。
答案 0 :(得分:3)
你正在分配这么多内存(在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;