Как исправить потоки на блок в графическом процессоре? - PullRequest
1 голос
/ 26 марта 2019

Я новичок в кодировании GPU с использованием CUDA.Я попробовал простой пример (как прикрепленный код) об использовании графического процессора.Когда я извлек 6 переменных с одинаковым значением, он отображался с другими результатами (например, 0 64832 64832 64832 0 64832 вместо 0 0 0 0 0 0).Однако, когда я меняю значение THREADS_PER_BLOCK с 1024 на 2, это работает.Можете ли вы помочь мне объяснить это явление?

Большое вам спасибо!

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <time.h>
using namespace std;
#define THREADGPU (360*180) 
#define THREADS_PER_BLOCK 1024

__global__ void calculation(double *xStartDraw, double *yStartDraw, double 
*zStartDraw,
double *xEndDraw, double *yEndDraw, double *zEndDraw)
{
int index = blockIdx.x * blockDim.x + threadIdx.x;

//cout with same value
xStartDraw[index] = index;
yStartDraw[index] = index;
zStartDraw[index] = index;
xEndDraw[index] = index;
yEndDraw[index] = index;
zEndDraw[index] = index;
}

int main(int argc, char **argv)
{
double *xStartDraw, *yStartDraw, *zStartDraw;
double *xEndDraw, *yEndDraw, *zEndDraw;
int size = THREADGPU * sizeof(double);
xStartDraw = (double *)malloc(size);
yStartDraw = (double *)malloc(size);
zStartDraw = (double *)malloc(size);
xEndDraw = (double *)malloc(size);
yEndDraw = (double *)malloc(size);
zEndDraw = (double *)malloc(size);

double *d_xStartDraw, *d_yStartDraw, *d_zStartDraw;
double *d_xEndDraw, *d_yEndDraw, *d_zEndDraw;
cudaMalloc((void **)&d_xStartDraw, size);
cudaMalloc((void **)&d_yStartDraw, size);
cudaMalloc((void **)&d_zStartDraw, size);
cudaMalloc((void **)&d_xEndDraw, size);
cudaMalloc((void **)&d_yEndDraw, size);
cudaMalloc((void **)&d_zEndDraw, size);

calculation <<< (THREADGPU + (THREADS_PER_BLOCK - 1)) / THREADS_PER_BLOCK, THREADS_PER_BLOCK
    >>> (d_xStartDraw, d_yStartDraw, d_zStartDraw, d_xEndDraw, d_yEndDraw, d_zEndDraw);

cudaMemcpy(xStartDraw, d_xStartDraw, size, cudaMemcpyDeviceToHost);
cudaMemcpy(yStartDraw, d_yStartDraw, size, cudaMemcpyDeviceToHost);
cudaMemcpy(zStartDraw, d_zStartDraw, size, cudaMemcpyDeviceToHost);
cudaMemcpy(xEndDraw, d_xEndDraw, size, cudaMemcpyDeviceToHost);
cudaMemcpy(yEndDraw, d_yEndDraw, size, cudaMemcpyDeviceToHost);
cudaMemcpy(zEndDraw, d_zEndDraw, size, cudaMemcpyDeviceToHost);


    for (int iRun = 0; iRun < THREADGPU; iRun++) 
    {
    cout <<iRun<<" "<<xStartDraw[iRun] <<" "<< yStartDraw[iRun] 
<<" "<< zStartDraw[iRun] <<" "<< xEndDraw[iRun] <<" "<< yEndDraw[iRun] <<" "<< zEndDraw[iRun] << endl;
}
free(xStartDraw);
free(yStartDraw);
free(zStartDraw);
free(xEndDraw);
free(yEndDraw);
free(zEndDraw);
cudaFree(d_xStartDraw);
cudaFree(d_yStartDraw);
cudaFree(d_zStartDraw);
cudaFree(d_xEndDraw);
cudaFree(d_yEndDraw);
cudaFree(d_zEndDraw);

return 0;
}

1 Ответ

2 голосов
/ 26 марта 2019

360 * 180 не делится поровну на 1024. Таким образом, не у всех потоков в вашем последнем блоке будет допустимый элемент для работы, в результате чего эти потоки обращаются к памяти за пределами.360 * 180, однако, делится поровну на 2, поэтому он работает тогда ...

Кроме того: не используйте malloc() в C ++.Рассмотрите возможность использования интеллектуальных указателей (например, std :: unique_ptr ) для управления распределением памяти.А вызовы API CUDA возвращают код ошибки, который вы должны проверить…

...