Добавление вектора в CUDA с использованием потоков

Я новичок в параллельном программировании CUDA. Я попробовал программу для добавления векторов с использованием потоков CUDA. Когда я компилирую, я получаю следующую ошибку.

Решение неверно. Решение не соответствовало ожидаемым результатам в строке 0. Ожидалось (1 + 0,5 = 1,5), но получилось 0.

Я проверил cuda с помощью примеров книг и подобных вопросов в Интернете. Не удалось найти решение. Может ли кто-нибудь помочь мне решить эту ошибку? Заранее спасибо.

#include <wb.h>
#define wbCheck(stmt) do { \
 cudaError_t err = stmt; \
 if (err != cudaSuccess) { \
 wbLog(ERROR, "Failed to run stmt ", #stmt); \
 wbLog(ERROR, "Got CUDA error ... ", cudaGetErrorString(err)); \
 return -1; \
 } \
} while(0)


__global__ void vecAdd(float * in1, float * in2, float * out, int len) 
{
int i = threadIdx.x + blockDim.x * blockIdx.x;
 if (i < len)
out[i] = in1[i] + in2[i];
}

int main(int argc, char ** argv) 
{
cudaStream_t stream0, stream1,stream2,stream3;
cudaStreamCreate(&stream0);
cudaStreamCreate(&stream1);
cudaStreamCreate(&stream2);
cudaStreamCreate(&stream3);
wbArg_t args;
int inputLength;

float *h_A, *h_B, *h_C;
float *d_A0, *d_B0, *d_C0;
float *d_A1, *d_B1, *d_C1;
float *d_A2, *d_B2, *d_C2;
float *d_A3, *d_B3, *d_C3;

args = wbArg_read(argc, argv);

wbTime_start(Generic, "Importing data and creating memory on host");
h_A = (float *) wbImport(wbArg_getInputFile(args, 0), &inputLength);
h_B = (float *) wbImport(wbArg_getInputFile(args, 1), &inputLength);
h_C = (float *) malloc(inputLength * sizeof(float));
wbTime_stop(Generic, "Importing data and creating memory on host");
wbLog(TRACE, "The input length is ", inputLength);
wbLog(TRACE, "h_A ", *h_A);
wbLog(TRACE, "h_B", *h_B);


int size = inputLength * sizeof(float);
int SegSize = inputLength/4;


wbCheck(cudaMalloc((void **) &d_A0, size));
wbCheck(cudaMalloc((void **) &d_B0, size));
wbCheck(cudaMalloc((void **) &d_C0, size));

wbCheck(cudaMalloc((void **) &d_A1, size));
wbCheck(cudaMalloc((void **) &d_B1, size));
wbCheck(cudaMalloc((void **) &d_C1, size));

wbCheck(cudaMalloc((void **) &d_A2, size));
wbCheck(cudaMalloc((void **) &d_B2, size));
wbCheck(cudaMalloc((void **) &d_C2, size));

wbCheck(cudaMalloc((void **) &d_A3, size));
wbCheck(cudaMalloc((void **) &d_B3, size));
wbCheck(cudaMalloc((void **) &d_C3, size));


cudaHostAlloc((void **) &h_A, size, cudaHostAllocDefault);
cudaHostAlloc((void **) &h_B, size, cudaHostAllocDefault);
cudaHostAlloc((void **) &h_C, size, cudaHostAllocDefault);


dim3 DimGrid((inputLength -1)/256 +1 , 1 , 1);
dim3 DimBlock(256 , 1, 1);


for (int i=0; i<size; i+="inputLength*4)" {="" cudamemcpyasync(d_a0,="" h_a+i,="" segsize*sizeof(float),cudamemcpyhosttodevice,="" stream0);="" cudamemcpyasync(d_b0,="" h_b+i,="" cudamemcpyasync(d_a1,="" h_a+i+segsize,="" segsize*sizeof(float),cudamemcpyhosttodevice,stream1);="" cudamemcpyasync(d_b1,="" h_b+i+segsize,="" cudamemcpyasync(d_a2,="" h_a+i+segsize+segsize,="" stream2);="" cudamemcpyasync(d_b2,="" h_b+i+segsize+segsize,="" cudamemcpyasync(d_a3,="" h_a+i+segsize+segsize+segsize,="" stream3);="" cudamemcpyasync(d_b3,="" h_b+i+segsize+segsize+segsize,="" vecadd<<<dimgrid,="" dimblock,="" 0,="" stream0="">>>(d_A0, d_B0, d_C0,inputLength);
vecAdd<<<dimgrid, dimblock,="" 0,="" stream1="">>>(d_A1, d_B1, d_C1,inputLength);
vecAdd<<<dimgrid, dimblock,="" 0,="" stream2="">>>(d_A2, d_B2, d_C2,inputLength);
vecAdd<<<dimgrid, dimblock,="" 0,="" stream3="">>>(d_A3, d_B3, d_C3,inputLength);


cudaDeviceSynchronize();


cudaMemcpyAsync(h_C+i, d_C0, SegSize*sizeof(float),cudaMemcpyDeviceToHost, stream0);
cudaMemcpyAsync(h_C+i+SegSize, d_C1, SegSize*sizeof(float),cudaMemcpyDeviceToHost,stream1);
cudaMemcpyAsync(h_C+i+SegSize+SegSize, d_C2, SegSize*sizeof(float),cudaMemcpyDeviceToHost,stream2);
cudaMemcpyAsync(h_C+i+SegSize+SegSize+SegSize, d_C3, SegSize*sizeof(float),cudaMemcpyDeviceToHost,stream3);
 wbLog(TRACE, "on addition is ", *h_C);

}

cudaFree(d_A0);
cudaFree(d_B0);
cudaFree(d_C0);

cudaFree(d_A1);
cudaFree(d_B1);
cudaFree(d_C1);

cudaFree(d_A2);
cudaFree(d_B2);
cudaFree(d_C2);

cudaFree(d_A3);
cudaFree(d_B3);
cudaFree(d_C3);

wbSolution(args, h_C, inputLength);
cudaFreeHost(h_A);
cudaFreeHost(h_B);
cudaFreeHost(h_C);

return 0;
}
</dimgrid,></dimgrid,></dimgrid,></size;></wb.h>
1 ответ

Одна из проблем заключается в том, как вы обрабатываете h_A, h_B и h_C:

h_A = (float *) wbImport(wbArg_getInputFile(args, 0), &inputLength);
h_B = (float *) wbImport(wbArg_getInputFile(args, 1), &inputLength);

Вышеупомянутые строки кода создают распределение для h_A и h_B и импортируют некоторые данные (предположительно).

Эти строки кода:

cudaHostAlloc((void **) &h_A, size, cudaHostAllocDefault);
cudaHostAlloc((void **) &h_B, size, cudaHostAllocDefault);
cudaHostAlloc((void **) &h_C, size, cudaHostAllocDefault);

Не делайте то, что думаете. Они создают новое распределение для h_A, h_B и h_C. Независимо от того, какие данные указатели, ранее упомянутые, больше не доступны из этих указателей (т.е. Для всех целей и целей, они теряются).

CUDA должен быть в состоянии отлично работать с создаваемыми здесь указателями и выделениями:

h_A = (float *) wbImport(wbArg_getInputFile(args, 0), &inputLength);
h_B = (float *) wbImport(wbArg_getInputFile(args, 1), &inputLength);
h_C = (float *) malloc(inputLength * sizeof(float));

Поэтому удалите эти строки кода:

cudaHostAlloc((void **) &h_A, size, cudaHostAllocDefault);
cudaHostAlloc((void **) &h_B, size, cudaHostAllocDefault);
cudaHostAlloc((void **) &h_C, size, cudaHostAllocDefault);

и удалите их:

cudaFreeHost(h_A);
cudaFreeHost(h_B);
cudaFreeHost(h_C);

И вы должны быть ближе к решению.

licensed under cc by-sa 3.0 with attribution.