使用CUDA实现神经网络

3

我想使用CUDA创建一个神经网络:

我的内核代码如下:

__global__ void feedForward(float *input, float *output, float **weight) {

//Here the threadId uniquely identifies weight in a neuron
int weightIndex = threadIdx.x;

//Here the blockId uniquely identifies a neuron
int neuronIndex = blockIdx.x;

if(neuronIndex<NO_OF_NEURONS && weightIndex<NO_OF_WEIGHTS)
output[neuronIndex] += weight[neuronIndex][weightIndex]
        * input[weightIndex];
}

在将输出复制回主机时,我遇到了一个错误。

错误未指定发生故障的行 xx。

在第 xx 行:

CUDA_CHECK_RETURN(cudaMemcpy(h_output, d_Output, output_size, cudaMemcpyDeviceToHost));

我在这里做错了什么吗?

是因为我同时使用块索引和线程索引来引用权重矩阵吗?还是问题出在其他地方?

我是按以下方式分配权重矩阵的:

cudaMallocPitch((void**)&d_Weight, &pitch_W,input_size,NO_OF_NEURONS);

我的内核调用是:

feedForward<<<NO_OF_NEURONS,NO_OF_WEIGHTS>>>(d_Input,d_Output,d_Weight);

之后我调用:

cudaThreadSynchronize();

我对使用CUDA进行编程还不熟悉。 任何帮助都将不胜感激。

谢谢


2
未指定的启动失败通常意味着您的内核未能执行某些操作。在复制之前检查错误。我敢打赌你没有以正确的方式复制权重。 - Pavan Yalamanchili
1
1). 你如何启动你的内核? 2). 写入输出数组时发生错误。一个块内的所有线程都会同时向单个内存单元写入数据。你可以用共享内存中的归约和单个全局内存写入来替换代码的这部分。 - Oleg Titov
你能提供内核初始化前后的主机代码吗? - Fr34K
根据要求,我已经添加了内存分配和内核启动的代码。 - Shayan RC
现在我看到这些代码片段,我觉得谷歌和Facebook被低估了! - Devi Prasad Khatua
显示剩余4条评论
3个回答

1

输出代码存在问题。虽然不会产生所描述的错误,但会产生不正确的结果。

int neuronIndex = blockIdx.x;

if(neuronIndex<NO_OF_NEURONS && weightIndex<NO_OF_WEIGHTS)
output[neuronIndex] += weight[neuronIndex][weightIndex] * input[weightIndex];

我们可以看到,单个块中的所有线程都同时写入一个内存单元。因此,预计会出现未定义的结果。为了避免这种情况,我建议在共享内存中减少块内的所有值,并执行一次对全局内存的单个写操作。类似于这样:
__global__ void feedForward(float *input, float *output, float **weight) {

  int weightIndex = threadIdx.x;
  int neuronIndex = blockIdx.x;
  __shared__ float out_reduce[NO_OF_WEIGHTS];

  out_reduce[weightIndex] = 
     (weightIndex<NO_OF_WEIGHTS && neuronIndex<NO_OF_NEURONS) ? 
       weight[neuronIndex][weightIndex] * input[weightIndex]
       : 0.0;
  __syncthreads();

  for (int s = NO_OF_WEIGHTS; s > 0 ; s >>= 1)
  {
    if (weightIndex < s) out_reduce[weightIndex] += out_reduce[weightIndex + s];
    __syncthreads();
  }

  if (weightIndex == 0) output[neuronIndex] += out_reduce[weightIndex]; 
}

原来我必须重写你的一半小内核以帮助减少代码...

谢谢你告诉我关于减少的事情。但它并没有解决问题。有人有其他的解决方案吗? - Shayan RC

1

0
你正在使用cudaMallocPitch,但没有展示变量如何初始化;我敢打赌这就是你的错误根源所在。cudaMallocPitch相当棘手;第三个参数应该是以字节为单位的,而第四个参数则不是。例如:
int width = 64, height = 64;
float* devPtr;
size_t pitch;
cudaMallocPitch(&device_Ptr, &pitch, width * sizeof(float), height);

你的变量input_size是以字节为单位吗?如果不是,那么你可能分配的内存太少了(即你认为你请求了64个元素,但实际上你只得到了64个字节),因此你将在内核中访问超出范围的内存。根据我的经验,“未指定的启动失败”错误通常意味着我有一个段错误。


'input_size' 是以字节为单位的。 它被初始化为:int input_size = NO_OF_WEIGHTS * sizeof(float); - Shayan RC
那么我想我们可以排除那个了。你在任何地方使用音高值吗? - alrikai
还没有...但是我以后需要将权重从设备复制到主机。 - Shayan RC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接