我有这些结构:
typedef struct neuron
{
float* weights;
int n_weights;
}Neuron;
typedef struct neurallayer
{
Neuron *neurons;
int n_neurons;
int act_function;
}NLayer;
“NLayer”结构可以包含任意数量的“Neuron”
我试图以这种方式从主机分配一个带有5个'神经元'的'NLayer'结构:
NLayer* nL;
int i;
int tmp=9;
cudaMalloc((void**)&nL,sizeof(NLayer));
cudaMalloc((void**)&nL->neurons,6*sizeof(Neuron));
for(i=0;i<5;i++)
cudaMemcpy(&nL->neurons[i].n_weights,&tmp,sizeof(int),cudaMemcpyHostToDevice);
...然后我尝试用该内核修改“nL-&gt; neural [0] .n_weights”变量:
__global__ void test(NLayer* n)
{
n->neurons[0].n_weights=121;
}
但是在编译时nvcc返回与内核唯一行相关的“警告”:
Warning: Cannot tell what pointer points to, assuming global memory space
当内核完成其工作时,struct开始无法访问。
很可能我在分配期间做错了什么......有人可以帮助我吗? 非常感谢,对不起我的英语! :)
更新
感谢aland我修改了我的代码,创建了这个函数,它应该分配一个struct“NLayer”的实例:
NLayer* setNLayer(int numNeurons,int weightsPerNeuron,int act_fun)
{
int i;
NLayer h_layer;
NLayer* d_layer;
float* d_weights;
//SET THE LAYER VARIABLE OF THE HOST NLAYER
h_layer.act_function=act_fun;
h_layer.n_neurons=numNeurons;
//ALLOCATING THE DEVICE NLAYER
if(cudaMalloc((void**)&d_layer,sizeof(NLayer))!=cudaSuccess)
puts("ERROR: Unable to allocate the Layer");
//ALLOCATING THE NEURONS ON THE DEVICE
if(cudaMalloc((void**)&h_layer.neurons,numNeurons*sizeof(Neuron))!=cudaSuccess)
puts("ERROR: Unable to allocate the Neurons of the Layer");
//COPING THE HOST NLAYER ON THE DEVICE
if(cudaMemcpy(d_layer,&h_layer,sizeof(NLayer),cudaMemcpyHostToDevice)!=cudaSuccess)
puts("ERROR: Unable to copy the data layer onto the device");
for(i=0;i<numNeurons;i++)
{
//ALLOCATING THE WEIGHTS' ARRAY ON THE DEVICE
cudaMalloc((void**)&d_weights,weightsPerNeuron*sizeof(float));
//COPING ITS POINTER AS PART OF THE i-TH NEURONS STRUCT
if(cudaMemcpy(&d_layer->neurons[i].weights,&d_weights,sizeof(float*),cudaMemcpyHostToDevice)!=cudaSuccess)
puts("Error: unable to copy weights' pointer to the device");
}
//RETURN THE DEVICE POINTER
return d_layer;
}
并且我以这种方式从main调用该函数(先前声明了内核“test”):
int main()
{
NLayer* nL;
int h_tmp1;
float h_tmp2;
nL=setNLayer(10,12,13);
test<<<1,1>>>(nL);
if(cudaMemcpy(&h_tmp1,&nL->neurons[0].n_weights,sizeof(float),cudaMemcpyDeviceToHost)!=cudaSuccess);
puts("ERROR!!");
printf("RESULT:%d",h_tmp1);
}
当我编译该代码时,编译器会向我显示警告,当我执行程序时,它会在屏幕上打印:
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
ERROR!!
RESULT:1
如果我评论内核调用,则最后一个错误不会比较。
我哪里错了? 我不知道该怎么做 谢谢你的帮助!
答案 0 :(得分:5)
问题在于:
cudaMalloc((void**)&nL,sizeof(NLayer));
cudaMalloc((void**)&nL->neurons,6*sizeof(Neuron));
在第一行中,nL
指向设备上的全局内存中的结构。
因此,在第二行中,cudaMalloc
的第一个参数是驻留在GPU上的地址,这是未定义的行为(在我的测试系统上,它会导致段错误;但在你的情况下,有一些更微妙的东西)。
执行所需操作的正确方法是首先在主机内存中创建结构,用数据填充,然后将其复制到设备,如下所示:
NLayer* nL;
NLayer h_nL;
int i;
int tmp=9;
// Allocate data on device
cudaMalloc((void**)&nL, sizeof(NLayer));
cudaMalloc((void**)&h_nL.neurons, 6*sizeof(Neuron));
// Copy nlayer with pointers to device
cudaMemcpy(nL, &h_nL, sizeof(NLayer), cudaMemcpyHostToDevice);
另外,不要忘记始终检查CUDA例程中的任何错误。
<强>更新强>
在您的代码的第二个版本中:
cudaMemcpy(&d_layer->neurons[i].weights,&d_weights,...)
---再次,您在主机上取消引用设备指针(d_layer
)。相反,你应该使用
cudaMemcpy(&h_layer.neurons[i].weights,&d_weights,sizeof(float*),cudaMemcpyHostToDevice
在这里你取h_layer
(主机结构),读取它的元素(h_layer.neurons
),它是指向设备内存的指针。然后你在它上面做一些指针算术(&h_layer.neurons[i].weights
)。无需访问设备内存即可计算此地址。
答案 1 :(得分:0)
这完全取决于您使用的GPU卡。费米卡使用统一寻址共享和全局存储空间,而费米卡则不会使用。
对于前费米案,您不知道该地址是应该共享还是全球。编译器通常可以解决这个问题,但有些情况下它无法解决。当需要指向共享内存的指针时,通常会获取共享变量的地址,编译器可以识别它。消息&#34;假设全球&#34;将在未明确定义时显示。
如果您使用的计算能力为2.x或更高的GPU,则应使用-arch = sm_20编译器标志