我怎样才能使用嵌套for循环加起来两个2d(pitched)数组?

我是新来的cuda。 我想把两个2d数组加到第三个数组中。 我使用以下代码:

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); 

现在我的问题是,我不想要使用这些数组作为扁平二维数组所有在我的内核代码我想迪是使用两个循环&把结果放在第三个数组像

 __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]; } } } 

我如何在CUDA中做到这一点? 请告诉我如何以这种方式使用二维数组?

内核调用2d数组应该是什么? 如果可能,请使用代码示例进行说明。

简短的回答是,你不能。 cudaMallocPitch()函数完全按照其名称的含义进行操作,它分配倾斜的线性内存,其中间距select为GPU内存控制器和纹理硬件的最佳select。

如果你想在内核中使用指针数组,内核代码将看起来像这样:

 __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]; } } } 

然后您需要在主机端嵌套cudaMalloc调用来构造指针数组并将其复制到设备内存。 对于你微不足道的2×2的例子,分配单个数组的代码如下所示:

 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); 

这将把分配的设备数组放在d_a中,并且将其传递给内核。

对于代码复杂性和性能的原因,你真的不希望这样做,在CUDA代码中使用指针数组比使用线性内存的替代方法更难更慢。


为了说明在CUDA中使用指针数组是否愚蠢,下面是一个完整的示例问题示例,它结合了上面的两个想法:

 #include <cstdio> __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(); } 

我build议你研究它,直到你明白它的作用,以及为什么它比使用线性内存是一个很糟糕的想法。

您不需要在设备内使用循环。 试试这个代码。

 #include <stdio.h> #include <cuda.h> #include <stdlib.h> #include <time.h> #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 <<<N,N>>> (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; }