Я использую CUDA для вычисления значений массива 64x64x4, который был сглажен. Массив содержит GLubytes, а затем в столбце z хранятся значения RGBA для любого заданного пикселя. Я создал ядро для использования с CUDA, но я считаю, что размеры моих блоков и сеток отключены. Конечный результат вместо рисования кругов, я рисую только четвертые круги. Ядро и функция, которая вызывает:
Для уточнения: ДИАМЕТР = 64, РАДИУС = 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;
}
Мой вопрос: моя проблема найдена в размерах моего блока и сетки? Или что-то еще?
Выход (один раз, когда я запускаю шарик через openGL), выглядит следующим образом:
Я должен добавить, что, когда я не использую cuda и просто вычисляю значения массива с регулярными циклами, логика, используемая внутри ядра, отлично работает и рисует круги.
Вы выделяете столько памяти (в 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;
Это превышает площадь 64x64x4 в ball
. Если вы запустили этот код с помощью cuda-memcheck
, я уверен, что вы увидите ошибки индексации вне пределов.
Кажется, что, возможно, индексирование вашего массива должно быть примерно таким:
ball[4 * ((x) * DIAMETER + (y))+0] = (GLubyte) 0xffffff;