PyTorch 中的"运行时错误:CUDA 错误:设备端断言触发"是什么意思?



我看过很多针对特定案例问题的具体帖子,但没有基本的激励解释。此错误有什么作用:

RuntimeError: CUDA error: device-side assert triggered

意味 着?具体来说,正在触发的断言是什么,为什么断言在那里,我们如何逆向工作以调试问题?

按原样,此错误消息在诊断任何问题时几乎毫无用处,因为它似乎普遍说"某处接触 GPU 的某些代码"有问题。Cuda 的文档在这方面似乎也没有帮助,尽管我可能是错的。 https://docs.nvidia.com/cuda/cuda-gdb/index.html

当我将代码转移到 CPU 而不是 GPU 上工作时,我收到以下错误:

IndexError: index 128 is out of bounds for dimension 0 with size 128

因此,也许代码中可能存在错误,由于某种奇怪的原因,该错误显示为CUDA错误。

当在 CUDA 设备代码运行时检测到设备端错误时,将通过通常的 CUDA 运行时 API 错误报告机制报告该错误。 设备代码中通常检测到的错误类似于非法地址(例如,尝试取消引用无效指针),但另一种类型是设备端断言。每当设备代码中出现 C/C++assert()并且断言条件为 false 时,就会生成这种类型的错误。

此类错误是由于特定内核而发生的。 CUDA 中的运行时错误检查必然是异步的,但可能至少有 3 种可能的方法可以开始调试它。

  1. 修改源代码,将异步内核启动有效转换为同步内核启动,并在每次内核启动后进行严格的错误检查。这将识别导致错误的特定内核。 此时,只需查看该内核代码中的各种断言就足够了,但您也可以使用下面的步骤 2 或 3。

  2. 使用cuda-memcheck运行代码。 这是一个类似于"设备代码的valgrind"的工具。 当您使用cuda-memcheck运行代码时,它的运行速度往往会慢得多,但运行时错误报告将得到增强。 通常最好使用-lineinfo编译代码。 在这种情况下,当触发设备端断言时,cuda-memcheck将报告断言所在的源代码行号,以及断言本身和 false 的条件。 您可以在此处查看使用它的演练(尽管使用非法地址错误而不是assert(),但assert()的过程将是相似的。

  3. 也应该可以使用调试器。 如果您使用调试器,例如cuda-gdb(例如在 linux 上),则调试器将具有回溯跟踪报告,这些报告将指示断言在命中时是哪一行。

如果从 python 脚本启动 CUDA 代码,则可以使用cuda-memcheck和调试器。

此时,您已经发现了断言是什么以及它在源代码中的位置。 为什么会在那里,不能笼统地回答。 这将取决于开发人员的意图,如果没有注释或其他明显,您将需要一些方法来以某种方式直觉。 "如何逆向工作"的问题也是一个通用的调试问题,而不是特定于 CUDA。 您可以在 CUDA 内核代码中使用printf,也可以使用像cuda-gdb这样的调试器来帮助解决这个问题(例如,在断言之前设置断点,并在断言即将命中时检查机器状态 - 例如变量)。

使用较新的GPU,您可能希望使用compute-sanitizer而不是cuda-memcheck。 它以类似的方式工作。

就我而言,导致此错误是因为我的损失函数只接收 [0, 1] 之间的值,并且我正在传递其他值。

因此,规范化我的损失函数输入,解决此问题:

saida_G -= saida_G.min(1, keepdim=True)[0]
saida_G /= saida_G.max(1, keepdim=True)[0]

阅读此内容:链接

最新更新