Вычисление двумерного массива пикселей с использованием CUDA, объявление правильных размеров сетки и блоков

0

Я использую 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), выглядит следующим образом: Изображение 174551

Я должен добавить, что, когда я не использую cuda и просто вычисляю значения массива с регулярными циклами, логика, используемая внутри ядра, отлично работает и рисует круги.

Теги:
arrays
opengl
cuda

1 ответ

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; 

Это превышает площадь 64x64x4 в ball. Если вы запустили этот код с помощью cuda-memcheck, я уверен, что вы увидите ошибки индексации вне пределов.

Кажется, что, возможно, индексирование вашего массива должно быть примерно таким:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню