Come posso sumre due array 2d (pitched) usando loop nested for?

Sono nuovo di cuda. Voglio aggiungere due array 2d in un terzo array. Io uso il seguente codice:

cudaMallocPitch((void**)&device_a, &pitch, 2*sizeof(int),2); cudaMallocPitch((void**)&device_b, &pitch, 2*sizeof(int),2); cudaMallocPitch((void**)&device_c, &pitch, 2*sizeof(int),2); 

ora il mio problema è che non voglio usare questi array come array 2-d appiattito tutto nel mio codice del kernel che voglio usare è due per loop e mettere il risultato nel terzo array come

 __global__ void add(int *dev_a ,int *dev_b,int* dec_c) { for i=0;i<2;i++) { for j=0;j<2;j++) { dev_c[i][j]=dev_a[i][j]+dev_b[i][j]; } } } 

Come posso farlo in CUDA? per favore dimmi come usare l’array 2-d in questo modo?

Quale dovrebbe essere la richiesta del kernel per l’utilizzo di 2d-array? Se ansible, spiegare con esempi di codice.

La risposta breve è, non puoi. La funzione cudaMallocPitch() fa esattamente ciò che il suo nome implica, alloca la memoria lineare lineare, in cui l’intonazione viene scelta come ottimale per il controller di memoria GPU e l’hardware di trama.

Se si desidera utilizzare matrici di puntatori nel kernel, il codice del kernel dovrebbe apparire come questo:

 __global___ void add(int *dev_a[] ,int *dev_b[], int* dec_c[]) { for i=0;i<2;i++) { for j=0;j<2;j++) { dev_c[i][j]=dev_a[i][j]+dev_b[i][j]; } } } 

e quindi avresti bisogno di chiamate cudaMalloc nidificate sul lato host per build l'array di puntatori e copiarlo nella memoria del dispositivo. Per il tuo esempio 2x2 piuttosto banale, il codice per allocare un singolo array sarebbe simile a questo:

 int ** h_a = (int **)malloc(2 * sizeof(int *)); cudaMalloc((void**)&h_a[0], 2*sizeof(int)); cudaMalloc((void**)&h_a[1], 2*sizeof(int)); int **d_a; cudaMalloc((void ***)&d_a, 2 * sizeof(int *)); cudaMemcpy(d_a, h_a, 2*sizeof(int *), cudaMemcpyHostToDevice); 

Il che lascerebbe l'array di puntatori di device assegnato in d_a, e lo passeresti al tuo kernel.

Per motivi di complessità del codice e di prestazioni, non si vuole davvero farlo, utilizzando gli array di puntatori nel codice CUDA è sia più difficile che più lento rispetto all'utilizzo della memoria lineare.


Per mostrare quale follia usare matrici di puntatori è in CUDA, ecco un esempio operativo completo del tuo problema campione che combina le due idee sopra:

 #include  __global__ void add(int * dev_a[], int * dev_b[], int * dev_c[]) { for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { dev_c[i][j]=dev_a[i][j]+dev_b[i][j]; } } } inline void GPUassert(cudaError_t code, char * file, int line, bool Abort=true) { if (code != 0) { fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code),file,line); if (Abort) exit(code); } } #define GPUerrchk(ans) { GPUassert((ans), __FILE__, __LINE__); } int main(void) { const int aa[2][2]={{1,2},{3,4}}; const int bb[2][2]={{5,6},{7,8}}; int cc[2][2]; int ** h_a = (int **)malloc(2 * sizeof(int *)); for(int i=0; i<2;i++){ GPUerrchk(cudaMalloc((void**)&h_a[i], 2*sizeof(int))); GPUerrchk(cudaMemcpy(h_a[i], &aa[i][0], 2*sizeof(int), cudaMemcpyHostToDevice)); } int **d_a; GPUerrchk(cudaMalloc((void ***)&d_a, 2 * sizeof(int *))); GPUerrchk(cudaMemcpy(d_a, h_a, 2*sizeof(int *), cudaMemcpyHostToDevice)); int ** h_b = (int **)malloc(2 * sizeof(int *)); for(int i=0; i<2;i++){ GPUerrchk(cudaMalloc((void**)&h_b[i], 2*sizeof(int))); GPUerrchk(cudaMemcpy(h_b[i], &bb[i][0], 2*sizeof(int), cudaMemcpyHostToDevice)); } int ** d_b; GPUerrchk(cudaMalloc((void ***)&d_b, 2 * sizeof(int *))); GPUerrchk(cudaMemcpy(d_b, h_b, 2*sizeof(int *), cudaMemcpyHostToDevice)); int ** h_c = (int **)malloc(2 * sizeof(int *)); for(int i=0; i<2;i++){ GPUerrchk(cudaMalloc((void**)&h_c[i], 2*sizeof(int))); } int ** d_c; GPUerrchk(cudaMalloc((void ***)&d_c, 2 * sizeof(int *))); GPUerrchk(cudaMemcpy(d_c, h_c, 2*sizeof(int *), cudaMemcpyHostToDevice)); add<<<1,1>>>(d_a,d_b,d_c); GPUerrchk(cudaPeekAtLastError()); for(int i=0; i<2;i++){ GPUerrchk(cudaMemcpy(&cc[i][0], h_c[i], 2*sizeof(int), cudaMemcpyDeviceToHost)); } for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { printf("(%d,%d):%d\n",i,j,cc[i][j]); } } return cudaThreadExit(); } 

Ti consiglio di studiarlo fino a quando non capisci cosa fa e perché è un'idea così scarsa rispetto all'uso della memoria lineare.

Non è necessario utilizzare per i loop all’interno del dispositivo. Prova questo codice.

 #include  #include  #include  #include  #define N 800 __global__ void matrixAdd(float* A, float* B, float* C){ int i = threadIdx.x; int j = blockIdx.x; C[N*j+i] = A[N*j+i] + B[N*j+i]; } int main (void) { clock_t start = clock(); float a[N][N], b[N][N], c[N][N]; float *dev_a, *dev_b, *dev_c; cudaMalloc((void **)&dev_a, N * N * sizeof(float)); cudaMalloc((void **)&dev_b, N * N * sizeof(float)); cudaMalloc((void **)&dev_c, N * N * sizeof(float)); for (int i = 0; i < N; i++){ for (int j = 0; j < N; j++){ a[i][j] = rand() % 10; b[i][j] = rand() % 10; } } cudaMemcpy(dev_a, a, N * N * sizeof(float), cudaMemcpyHostToDevice); cudaMemcpy(dev_b, b, N * N * sizeof(float), cudaMemcpyHostToDevice); matrixAdd <<>> (dev_a, dev_b, dev_c); cudaMemcpy(c, dev_c, N * N * sizeof(float), cudaMemcpyDeviceToHost); for (int i = 0; i < N; i++){ for (int j = 0; j < N; j++){ printf("[%d, %d ]= %f + %f = %f\n",i,j, a[i][j], b[i][j], c[i][j]); } } printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC); cudaFree(dev_a); cudaFree(dev_b); cudaFree(dev_c); return 0; }