2011-05-26 18 views
9

我是新來的cuda。我想將兩個2d數組加到第三個數組中。 我用下面的代碼:如何使用嵌套for循環來合計兩個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); 

我現在的問題是,我不想爲扁平的2-d陣列 都在我的內核代碼,我想迪使用這些陣列使用兩個for循環&把結果在第三個陣列中就像

__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數組? 如果可能,請使用代碼示例進行說明。

+1

請格式化代碼 - 縮進4個空格。 – sje397 2011-05-26 10:41:44

回答

16

簡短的回答是,你不能。 cudaMallocPitch()功能正如其名稱所暗示的那樣,它分配傾斜線性內存,其中間距選擇爲GPU存儲器控制器和紋理硬件的最佳選擇。

如果你想使用的內核指針數組,內核代碼必須是這樣的:

__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調用構造指針陣列並將其複製到設備內存。爲了您的相當瑣碎的2x2例如,代碼分配一個單一陣列是這樣的:

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

我建議你研究它,直到你瞭解它的功能,以及與使用線性內存相比,它爲何如此糟糕。

+0

是的你是對的。現在假設我這樣做什麼應該是我的內核電話 – user513164 2011-05-26 11:54:52

+0

謝謝。是的,你是對的。現在假設我做了這個應該是我的內核調用?有一件事我會說我使用cudaMalloc((void ***)&d_a,2 * sizeof(int *));但它顯示錯誤; h_a還有一件事爲什麼你使用cuda malloc請詳細解釋 – user513164 2011-05-26 12:01:53

2

您不需要在設備內使用for循環。試試這個代碼。

#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; 
} 
+1

這適用於靜態分配的數組,只有在編譯時已知尺寸的情況下。對於問題中指出的任何類型的動態分配(例如'cudaMalloc'等),這將不起作用。 – 2014-06-02 16:01:00

+0

順便提一下,在將數組傳遞給內核之前,仍然會將數組扁平化,這並不是用戶想要的內容。 – MuneshSingh 2017-02-12 05:47:34