【发布时间】:2019-11-20 18:04:27
【问题描述】:
由于请求的资源过多,我遇到了内核启动失败的问题。我理解这个错误,我可以减少我的块大小来避免它,但我正在努力解决这个问题。
我正在使用 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 dev 上看到过一些较早的帖子讨论过这个问题,但它们似乎已经过时了。
编辑:
感谢 Michael 在这篇文章中的介绍,我发现我拥有的 GPU 实际上每个线程有 255 个寄存器。所以,寄存器不是问题。但是,这让我不确定问题出在哪里。
我认为包含我没有使用任何特定的编译器选项也是有益的。我曾经尝试过 -ptxas,但它并没有太大变化。
我不想减小 blocksize 块大小,因为在需要外部信息之前我可以进行的计算次数取决于 blocksize 的最小尺寸(x 或 y)。块大小越大,可能的计算就越多。
编辑: 所以,据我了解,我仍然超过了每个 SM 的寄存器总数,这是导致问题的原因。我需要减少使用的寄存器或块大小。
【问题讨论】:
-
根本原因将编译器优化。不会导致写入共享内存或全局内存的代码将被编译器优化掉,从而减少寄存器占用空间
-
每个线程注册,当考虑跨线程块时,例如1024 个线程,可能 是 的问题。如果答案让您不相信,那将是不幸的。答案的中间段落可能会让您感到困惑。是的,单个线程有 255 个寄存器的限制,但线程块(或 SM,如果您愿意)也有 65,536 个寄存器的聚合限制。因此,当您使用 65536 个寄存器并除以 1024 个线程时,每个线程最多只剩下 64 个寄存器,否则您的内核启动将失败,您收到的正是失败消息。
-
这有助于解决问题,谢谢罗伯特!