CUDA,复制到共享内存会大大增加使用的寄存器数量

时间:2019-07-11 05:22:07

标签: cuda pycuda

我遇到了内核启动失败的问题,因为请求的资源过多。我理解该错误,并且可以减小块大小来避免它,但是我正设法解决该问题。

我正在使用Nvidia Tesla K40c GPU。 我正在使用pycuda解决PDE系统。因此,我的目标是对每个线程进行一些本地计算,然后将其写入共享内存阵列。我对GPU计算还很陌生,但是我对眼前问题的了解如下。 此问题与下面的代码片段中注释掉的代码行有关。我知道共享内存非常适合块中的线程间通信,并且我的共享内存可以正常工作,直到我尝试从我假设存储在寄存器中的局部变量写入共享内存为止。我之所以这样假设,是因为我读取的数组小于特定大小,如果我没记错的话,则为16个浮点数,可以存储在寄存器中。矿山大小为4。无论如何,这是避免在全球范围内存储的目标。

__device__
void step(float *shared_state, int idx)
{
  float dfdxy[NVC]={0};
  get_dfdx(dfdxy,shared_state,idx);
  get_dfdy(dfdxy,shared_state,idx);
  __syncthreads();
  //shared_state[idx+0*SGIDS] += dfdxy[0];
}

这是痕迹。如前所述,我对错误很熟悉。

Traceback (most recent call last):
  File "./src/sweep/sweep.py", line 325, in <module>
    sweep(arr0,targs,order,block_size,euler.step,0)
  File "./src/sweep/sweep.py", line 109, in sweep
    gpu_speed(arr, source_mod, cpu_fcn, block_size,ops,num_tries=20)
  File "./src/sweep/sweep.py", line 175, in gpu_speed
    gpu_fcn(arr_gpu,grid=grid_size, block=block_size,shared=shared_size)
  File "/home/walkanth/.conda/envs/pysweep/lib/python3.6/site-packages/pycuda/driver.py", line 402, in function_call
    func._launch_kernel(grid, block, arg_buf, shared, None)
pycuda._driver.LaunchError: cuLaunchKernel failed: too many resources requested for launch

问题特别是在运行带有注释行的代码时出现的。它说我正在使用32个寄存器。很好,一切正常,因为我低于63的限制。

但是,当我取消注释该行时,使用的寄存器数量会猛增到70个,我怀疑这就是内核启动失败的原因。

所以,有几个问题。

首先,有人可以解释为什么会这样吗?我一直在寻找,但没有达到目标。

第二,如果没有解决办法。除了减少block_size之外,有人知道减少我的寄存器使用率的一些技巧吗? 我已经看到nvidia开发人员的一些较旧的话题对此进行了讨论,但是它们似乎过时了。

编辑:

因此,感谢Michael在这篇文章中,我发现我实际上每个线程有255个寄存器的GPU。因此,寄存器不是问题。但是,这使我不确定问题出在哪里。

我认为,包括不使用任何特定的编译器选项也将是有益的。我曾经尝试过-ptxas,但是并没有太大改变。

我不想减小块大小的块大小,因为在需要外部信息之前我可以进行的计算数量取决于块大小的最小尺寸(x或y)。块大小越大,可能进行的计算就越多。

编辑: 因此,据我了解,我仍然超出了每个SM的寄存器总数,这是导致此问题的原因。我需要减少使用的寄存器或块大小。

1 个答案:

答案 0 :(得分:0)

编译器将尝试自动优化寄存器指令的数量;如果您编写的代码最终不会在线程外的任何地方存储信息,则根本不应该生成这些指令。这可能就是为什么取消注释写入共享内存的行的注释时,寄存器数量会有很大变化的原因。

但是,根据https://developer.nvidia.com/cuda-gpus,K40c是计算能力3.5,而根据https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#compute-capabilities,具有计算能力3.5的设备每个线程最多可以有255个寄存器,而不是63个。您仍然每个线程仅使用70个寄存器,那么这可能不是问题。如果不再通过减小块大小来得到错误,则可以确认这一点;减小块大小会减少块中的线程数,但不应更改每个线程使用多少个寄存器,因此,如果实际上每个线程的寄存器都用完了,那么它就不能解决您的问题。

如果没有对编译器选项,内核其余部分以及如何启动它的进一步了解,我们将无法轻松确定资源问题是什么。每个块的寄存器数量和每个多处理器的寄存器数量也受到限制。如果减小块大小可以解决问题,则可能是您超过了这些阈值...,并且需要减小块大小。目前尚不清楚为什么不希望减小块大小,但是似乎您只是在遇到硬件限制。