Bak*_*123 2 c struct cuda dynamic-memory-allocation
将struct数组传递给gpu内核时遇到问题.我基于这个主题 - cudaMemcpy分段错误,我写了这样的:
#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);
for(int i=0; i < n; i++) {
cudaMalloc((void**)&(test[i].array), size * sizeof(char));
cudaMemcpy(&(dev_test[i].array), &(test[i].array), size * sizeof(char), cudaMemcpyHostToDevice);
}
kernel<<<1, 1>>>(dev_test);
cudaDeviceSynchronize();
// memory free
return 0;
}
Run Code Online (Sandbox Code Playgroud)
没有错误,但内核中显示的值不正确.我做错了什么?提前感谢您的帮助.
这是为主机内存分配一个新指针:
test[i].array = (char*)malloc(size * sizeof(char));
Run Code Online (Sandbox Code Playgroud)这是将数据复制到主机内存中的该区域:
memcpy(test[i].array, temp, size * sizeof(char));
Run Code Online (Sandbox Code Playgroud)这将使用指向设备内存的新指针覆盖先前分配给主机内存的指针(来自上面的步骤1):
cudaMalloc((void**)&(test[i].array), size * sizeof(char));
Run Code Online (Sandbox Code Playgroud)在步骤3之后,您在步骤2中设置的数据将完全丢失,并且无法以任何方式访问.请参阅您链接的问题/答案中的步骤3和4 :
3.在主机上创建一个单独的int指针,让我们调用它
myhostptr4.cudaMalloc int存储在设备上
myhostptr
你还没有这样做.您没有创建单独的指针.您重复使用(擦除,覆盖)现有指针,该指针指向您在主机上关注的数据. 这个问题/答案也与您链接的答案相关联,在代码中几乎完全按照您需要遵循的步骤进行操作.
这是您的代码的修改版本,它正确地实现了您未根据您链接的问题/答案正确实现的缺失步骤3和4(和5):(请参阅描述步骤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);
// Step 3:
char *temp_data[n];
// Step 4:
for (int i=0; i < n; i++)
cudaMalloc(&(temp_data[i]), size*sizeof(char));
// Step 5:
for (int i=0; i < n; i++)
cudaMemcpy(&(dev_test[i].array), &(temp_data[i]), sizeof(char *), cudaMemcpyHostToDevice);
// now copy the embedded data:
for (int i=0; i < n; i++)
cudaMemcpy(temp_data[i], test[i].array, size*sizeof(char), cudaMemcpyHostToDevice);
kernel<<<1, 1>>>(dev_test);
cudaDeviceSynchronize();
// memory free
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
$
Run Code Online (Sandbox Code Playgroud)
由于上述方法对于初学者来说可能具有挑战性,因此通常的建议不是这样做,而是将数据结构扁平化.展平通常意味着重新排列数据存储,以便移除必须单独分配的嵌入指针.
扁平化这种数据结构的一个简单例子就是使用它:
struct Test {
char array[5];
};
Run Code Online (Sandbox Code Playgroud)
当然,人们认识到这种特殊的方法并不能用于所有目的,但它应该说明一般的想法/意图.通过该修改,作为示例,代码变得更加简单:
$ 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();
// memory free
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
$
Run Code Online (Sandbox Code Playgroud)