2011-03-30 77 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计算统一设备架构