1

我已经阅读了以下线程,但我无法让我的代码工作。
我正在尝试在 GPU 上分配一个二维数组,用值填充它,然后将其复制回 CPU。我的代码如下:

__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

我怎样才能做到这一点?

4

4 回答 4

3

您无法在主机代码中操作设备指针,这就是循环内的 cudaMalloc 调用失败的原因。您可能应该只分配一个连续的内存块,然后将其视为扁平的二维数组。

于 2011-03-30T19:19:05.303 回答
1

对于在 GPU 上执行最简单的 2D 操作,我建议您将其视为 1D 数组。cudaMalloc 大小为 w*h*sizeof(char) 的块。您可以通过索引 j*w+i 访问元素 (i,j)。

或者,您可以使用cudaMallocArray获取二维数组。这比线性映射的 2D 内存具有更好的局部性。例如,您可以轻松地将其绑定到纹理。

现在就您的示例而言,它不起作用的原因是 cudaMalloc 操纵主机指针指向设备内存块。您的示例在设备上为 results_d 分配了指针结构。如果您只是将 results_d 的 cudaMalloc 调用更改为常规 malloc,它应该可以按您最初的预期工作。

也就是说,从易于代码维护的角度来看,我上面概述的两个选项之一可能会更好。

于 2011-04-03T12:07:18.930 回答
0

以这种方式分配时,您分配的地址在 CPU 内存上有效。地址的值作为数字传输没有问题,但一旦在设备内存中,char* 地址将没有意义。

创建一个 N * 最大文本长度的数组,以及另一个长度为 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> <<<>>> ()
于 2011-03-30T20:48:16.337 回答
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 数组复制到前面代码示例 [1] 中分配的 CUDA 数组:

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

于 2013-06-30T10:34:06.947 回答