CUDA:在GPU上分配2D阵列

时间:2011-03-30 19:13:45

标签: cuda

我已经阅读了以下thread ,但我无法使用我的代码。
我试图在GPU上分配一个2D数组,用值填充它,然后将其复制回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 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

为了在GPU上进行最简单的2D操作,我建议您将其视为一维数组。 cudaMalloc一个大小为w * h * sizeof(char)的块。您可以通过索引j * w + i。

访问元素(i,j)

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

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

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

答案 2 :(得分: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> <<<>>> ()

答案 3 :(得分: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);

以下代码示例将somehost内存阵列复制到设备内存[1]:

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

您可以理解这些示例并将其应用于您的目的。

[1] NVIDIA CUDA计算统一设备架构

相关问题