我已经看到很多针对特定案例的问题的特定帖子,但是没有根本的动机解释。这是什么错误:
RuntimeError: CUDA error: device-side assert triggered
是什么意思?具体来说,什么是触发的断言,为什么断言在那里,以及我们如何向后工作以调试问题?
按原样,此错误消息在诊断任何问题时几乎没有用,因为一般性地说,“某些与GPU接触的代码”存在问题。 Cuda的文档在这方面似乎也没有帮助,尽管我可能是错的。 https://docs.nvidia.com/cuda/cuda-gdb/index.html
答案 0 :(得分:3)
当我将代码转移到 CPU 而不是 GPU 上时,出现以下错误:
IndexError: index 128 is out of bounds for dimension 0 with size 128
所以,也许代码中可能有一个错误,出于某种奇怪的原因,它显示为 CUDA 错误。
答案 1 :(得分:1)
在运行CUDA设备代码时检测到设备端错误时,该错误将通过通常的CUDA runtime API error reporting mechanism报告。在设备代码中通常检测到的错误将类似于非法地址(例如,尝试取消引用无效的指针),但是另一种类型是设备端的断言。每当在设备代码中发生C / C ++ assert()
并且断言条件为false时,都会生成此类错误。
由于特定内核而导致发生错误。 CUDA中的运行时错误检查必须是异步的,但是可能至少有3种可能的方法可以开始对此进行调试。
修改源代码,以有效地将异步内核启动转换为同步内核启动,并在每次内核启动后进行严格的错误检查。这将确定导致错误的特定内核。到那时,仅查看该内核代码中的各个断言可能就足够了,但是您也可以使用下面的步骤2或3。
使用cuda-memcheck
运行代码。这是一个类似于“设备代码的valgrind”的工具。当您使用cuda-memcheck
运行代码时,它的运行速度往往会慢得多,但会增强运行时错误报告。通常最好使用-lineinfo
来编译代码。在那种情况下,当触发设备端断言时,cuda-memcheck
将报告断言所在的源代码行号,以及断言本身和为假的条件。您可以看到here的使用说明(尽管地址错误而不是assert()
,但是使用assert()
的过程与此类似。
还应该可以使用调试器。如果您使用cuda-gdb
之类的调试器(例如在Linux上),则该调试器将具有回溯报告,这些报告将指出断言所在的行以及命中的时间。
如果从Python脚本启动CUDA代码,则可以同时使用cuda-memcheck
和调试器。
在这一点上,您已经发现了断言是什么以及它在源代码中的位置。为什么会在那里不能被普遍回答。这将取决于开发人员的意图,并且如果未对其进行评论或以其他方式显而易见,则您将需要某种方法来以某种方式进行理解。 “如何向后工作”问题也是一个通用的调试问题,并非特定于CUDA。您可以在CUDA内核代码中使用printf
,还可以使用cuda-gdb
之类的调试器来解决此问题(例如,在断言之前设置断点,并在断言时检查机器状态(例如变量)即将被击中)。
答案 2 :(得分:1)
在我的例子中,这个错误是因为我的损失函数只接收 [0, 1] 之间的值,而我正在传递其他值。
所以,标准化我的损失函数输入,解决这个问题:
saida_G -= saida_G.min(1, keepdim=True)[0]
saida_G /= saida_G.max(1, keepdim=True)[0]
阅读:link