我想以不同的方式将结构数组从主机复制到设备。我可以通过电缆将完整的结构从主机复制到设备,但无法将结构的单个元素从主机复制到设备,而其中一个元素是指针变量。我在执行此操作时遇到段错误。指针变量会出现问题,普通变量不会出现问题。
我调试并发现错误位于下面一行。
cudaMemcpy(d_s[i].data,h_s[i].data,sizeof(float*),cudaMemcpyHostToDevice);
我无法解决这个问题。
#include<iostream>
using namespace std;
struct structure
{
int count;
float *data;
};
structure * fillStructure(int n, float *tdata )
{
structure *h_s;
h_s = (structure *) malloc( n * sizeof(structure));
for(int i =0; i< n; i++)
{
h_s[i].count =i;
h_s[i].data = &tdata[i];
}
cout<<"Input:\n";
for(int i=0; i<n ;i++)
{
cout<<h_s[i].count<<"\t";
}
cout<<endl;
for(int i=0; i<n ;i++)
{
cout<<*(h_s[i].data)<<"\t";
}
cout<<endl;
structure *d_s;
cudaMalloc((void**)&d_s, n * sizeof(structure));
for(int i=0; i<n ;i++)
{
cudaMemcpy(&d_s[i].count,&h_s[i].count, sizeof(int), cudaMemcpyHostToDevice);
cudaMemcpy(d_s[i].data,h_s[i].data,sizeof(float *),cudaMemcpyHostToDevice);
}
1,1 Top
return d_s;
}
int main()
{
int N =5;
float *ldata;
ldata = (float*) malloc(N * sizeof(float));
for(int i=0 ; i< N ; i++)
{
ldata[i] =i*i;
}
structure *ps = fillStructure(N, ldata);
structure *ls;
ls =(structure *) malloc( N * sizeof(structure));
cudaMemcpy(ls,ps,N * sizeof(structure),cudaMemcpyDeviceToHost);
cout<<"Result:\n";
for(int i=0; i< N;i++)
{
cout<<ls[i].count<<"\t";
}
cout<<endl;
for(int i =0 ; i< N; i++)
{
cout<<*(ls[i].data)<<"\t";
}
cout<<endl;
}
预期输出是
Input:
0 1 2 3 4
0 1 4 9 16
Result:
Input:
0 1 2 3 4
0 1 4 9 16
但实际输出是
Input:
0 1 2 3 4
0 1 4 9 16
Segmentation fault (core dumped)
提前致谢
最佳答案
关于这一行:
cudaMemcpy(d_s[i].data,h_s[i].data,sizeof(float *),cudaMemcpyHostToDevice);
您要求cudaMemcpy
做的是:
- 从
h_s[i].data
中检索源指针 - 使用该指针,从该指针指向的位置检索
float *
数量 - 从
d_s[i].data
中检索目标指针 - 使用该指针,将第 2 步中检索到的数量存储到第 3 步中的指针所指向的任何位置。
这会带来各种各样的问题,但最基本的问题是这并不是您真正想要做的。
您尝试复制的是(源位置)h_s[i].data
中包含的指针值,并且您希望将其存储在(目标)d_s[i ].data
。为了实现这一点,您必须传递一个指向这些位置(源和目标)的指针。
您可以通过向这两项添加 & 符号来解决此问题:
cudaMemcpy(&(d_s[i].data),&(h_s[i].data),sizeof(float *),cudaMemcpyHostToDevice);
这应该可以修复段错误。并且它会正确地将h_s[i].data
中包含的指针数值复制到d_s[i].data
。
但是,正如我之前向您所说的,您从源位置复制的指针在此处设置:
h_s[i].data = &tdata[i];
这是一个指向主机内存中某个位置的指针。这样的指针不能安全地在 CUDA 设备代码中使用,因此努力将该指针正确复制到设备实际上没有多大意义。它在设备代码中将毫无用处。
您仍然没有掌握 CUDA 深拷贝使该方案发挥作用的必要性。如前所述,这是按步骤方式介绍的 here .
关于cuda - 如何在 CUDA 中将结构体数组的指针变量从主机复制到设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58392069/