2011-03-30 76 views
1

我已閱讀以下thread,但無法讓我的代碼正常工作。
我想在GPU上分配一個二維數組,並用值填充它,然後將其複製回CPU。我的代碼如下:CUDA:在GPU上分配2D陣列

__global__ void Kernel(char **result,int N) 
{ 
    //do something like result[0][0]='a'; 
} 
int N=20; 
int Count=5; 
char **result_h=(char**)malloc(sizeof(char*)*Count); 
char **result_d; 
cudaMalloc(&result_d, sizeof(char*)*Count); 
for(int i=0;i<Count;i++) 
{ 
    result_h[i] = (char*)malloc(sizeof(char)*N);  
    cudaMalloc(&result_d[i], sizeof(char)*N); //get exception here 
} 

//call kernel 
//copy values from result_d to result_h 
printf("%c",result_h[0][0])//should print a 

我該如何做到這一點?

回答

3

您不能在主機代碼中操作設備指針,這就是爲什麼循環內的cudaMalloc調用失敗。你應該只是分配一個連續的內存塊,然後把它當作一個平坦的二維數組。

0

以這種方式進行分配時,您正在分配CPU內存上有效的地址。 地址的值作爲一個數字傳輸沒有問題,但一旦在設備內存上,char *地址就沒有意義。

創建一個N * max文本長度的數組,以及另一個長度爲N的數組,它告訴每個單詞有多長。

這是一個比較先進的,但如果你正在處理一組定義的文本(如密碼爲例) 我建議你到組它的文本長度和每個長度

template<int text_width> 
__global__ void Kernel(char *result,int N) 
{ 
    //pseudocode 
    for i in text_width: 
     result[idx][i] = 'a' 
} 

創建專門的內核而在內核調用代碼指定:

switch text_length 
case 16: 
    Kernel<16> <<<>>>() 
1

換做在GPU上最簡單的2D操作,我建議你只把它作爲一維數組。 cudaMalloc是一個大小爲w * h * sizeof(char)的塊。您可以通過索引j * w + i訪問元素(i,j)。您也可以使用cudaMallocArray來獲得2D數組。這比線性映射2D存儲器具有更好的局部感。例如,您可以輕鬆將其綁定到紋理。

現在就你的例子來說,它不起作用的原因是cudaMalloc操縱主機指針來指向設備內存塊。你的例子爲設備上的results_d分配了指針結構。如果您只是將results_d的cudaMalloc調用更改爲正常的malloc,則它應該按照您最初的預期工作。

也就是說,也許我從上面列出的兩個選項中的一個可能會更容易從代碼維護的角度來看。

0

下面的代碼示例分配一個寬×浮點值的高度2D陣列,並顯示如何循環在設備代碼數組元素[1]

// host code 

float* devPtr; 

int pitch; 

cudaMallocPitch((void**)&devPtr, &pitch, width * sizeof(float), height); 

myKernel<<<100, 192>>>(devPtr, pitch); 

// device code 
__global__ void myKernel(float* devPtr, int pitch) 

{ 
for (int r = 0; r < height; ++r) { 

    float* row = (float*)((char*)devPtr + r * pitch); 

    for (int c = 0; c < width; ++c) { 
      float element = row[c]; } 
              } 
} 

以下代碼示例分配一個寬×一個32位 浮點組件的高度CUDA陣列[1]

cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>(); 
cudaArray* cuArray; 
cudaMallocArray(&cuArray, &channelDesc, width, height); 

下面的代碼示例拷貝2D陣列到 前面的代碼示例中分配的CUDA數組[1]:

cudaMemcpy2DToArray(cuArray, 0, 0, devPtr, pitch, width * sizeof(float), height, 
cudaMemcpyDeviceToDevice); 

下面的代碼示例副本,某存儲器陣列到設備存儲器[1]:

float data[256]; 
int size = sizeof(data); 
float* devPtr; 
cudaMalloc((void**)&devPtr, size); 
cudaMemcpy(devPtr, data, size, cudaMemcpyHostToDevice); 

可以理解論文的例子和在你的目的應用它們。

[1] NVIDIA CUDA計算統一設備架構