我已经阅读了以下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
我怎样才能实现这个目标?
答案 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计算统一设备架构