这将为主机内存分配一个新指针:
test[i].array = (char*)malloc(size * sizeof(char));
这是将数据复制到主机内存中的那个区域:
memcpy(test[i].array, temp, size * sizeof(char));
这是用一个指向设备内存的新指针覆盖了之前分配给主机内存的指针(来自上面第1步),进行覆写操作:
cudaMalloc((void**)&(test[i].array), size * sizeof(char));
在第三步之后,你在第二步中设置的数据将完全丢失,并且无法以任何方式访问。参考你提供的
问题/回答中的第三步和第四步:
3. 在主机上创建一个名为myhostptr的独立int指针
4. 在设备上使用cudaMalloc为myhostptr分配int存储空间
你没有这样做。你没有创建一个单独的指针。你重复使用了(擦除,覆盖)指向主机上你关心的数据的现有指针。
这个问题/回答,也是你提供的答案中链接的,几乎完全给出了你需要按顺序遵循的步骤(在代码中)。
下面是你的代码的修改版本,它正确地实现了你根据你提供的问题/回答中未正确实现的第三步、第四步和第五步:(参见标记第3、4、5步的注释)
$ cat t755.cu
#include <stdio.h>
#include <stdlib.h>
struct Test {
char *array;
};
__global__ void kernel(Test *dev_test) {
for(int i=0; i < 5; i++) {
printf("Kernel[0][i]: %c \n", dev_test[0].array[i]);
}
}
int main(void) {
int n = 4, size = 5;
Test *dev_test, *test;
test = (Test*)malloc(sizeof(Test)*n);
for(int i = 0; i < n; i++)
test[i].array = (char*)malloc(size * sizeof(char));
for(int i=0; i < n; i++) {
char temp[] = { 'a', 'b', 'c', 'd' , 'e' };
memcpy(test[i].array, temp, size * sizeof(char));
}
cudaMalloc((void**)&dev_test, n * sizeof(Test));
cudaMemcpy(dev_test, test, n * sizeof(Test), cudaMemcpyHostToDevice);
char *temp_data[n];
for (int i=0; i < n; i++)
cudaMalloc(&(temp_data[i]), size*sizeof(char));
for (int i=0; i < n; i++)
cudaMemcpy(&(dev_test[i].array), &(temp_data[i]), sizeof(char *), cudaMemcpyHostToDevice);
for (int i=0; i < n; i++)
cudaMemcpy(temp_data[i], test[i].array, size*sizeof(char), cudaMemcpyHostToDevice);
kernel<<<1, 1>>>(dev_test);
cudaDeviceSynchronize();
return 0;
}
$ nvcc -o t755 t755.cu
$ cuda-memcheck ./t755
========= CUDA-MEMCHECK
Kernel[0][i]: a
Kernel[0][i]: b
Kernel[0][i]: c
Kernel[0][i]: d
Kernel[0][i]: e
========= ERROR SUMMARY: 0 errors
$
由于以上方法对于初学者来说可能会有一定的挑战性,通常的建议是不要使用它,而是 扁平化 数据结构。 扁平化通常意味着重新排列数据存储方式,以便删除必须单独分配的嵌套指针。
扁平化此数据结构的一个微不足道的示例将使用此内容:
struct Test {
char array[5];
};
当然,这种特定方法并不适用于每个目的,但它应该说明一般的想法/意图。通过这种修改,例如,代码变得更简单:
$ cat t755.cu
#include <stdio.h>
#include <stdlib.h>
struct Test {
char array[5];
};
__global__ void kernel(Test *dev_test) {
for(int i=0; i < 5; i++) {
printf("Kernel[0][i]: %c \n", dev_test[0].array[i]);
}
}
int main(void) {
int n = 4, size = 5;
Test *dev_test, *test;
test = (Test*)malloc(sizeof(Test)*n);
for(int i=0; i < n; i++) {
char temp[] = { 'a', 'b', 'c', 'd' , 'e' };
memcpy(test[i].array, temp, size * sizeof(char));
}
cudaMalloc((void**)&dev_test, n * sizeof(Test));
cudaMemcpy(dev_test, test, n * sizeof(Test), cudaMemcpyHostToDevice);
kernel<<<1, 1>>>(dev_test);
cudaDeviceSynchronize();
return 0;
}
$ nvcc -o t755 t755.cu
$ cuda-memcheck ./t755
========= CUDA-MEMCHECK
Kernel[0][i]: a
Kernel[0][i]: b
Kernel[0][i]: c
Kernel[0][i]: d
Kernel[0][i]: e
========= ERROR SUMMARY: 0 errors
$
cudaMalloc((void**)&(test[i].array), size * sizeof(char));
而不是cudaMalloc((void**)&(dev_test[i].array), size * sizeof(char));
? 另外,应该使用cudaMemcpy(dev_test[i].array, test[i].array, size * sizeof(char), cudaMemcpyHostToDevice);
。 - francisdev_test[i].array
分配内存,而不是为test[i].array
分配内存;test[i].array
已经通过test[i].array = (char*)malloc(size * sizeof(char));
在 CPU 上分配了内存。 - francistest[i].array
已经在CPU上分配了内存,但是在GPU上没有分配。我们无法为dev_test[i].array
分配内存,因为这块内存只能从设备上访问。至少我是这样理解的。 - Bakus123