问题
报错RuntimeError: CUDA error: device-side assert triggeredCUDA kernel errors might be asynchronous
报错原因分析
完整报错:
RuntimeError: CUDA error: device-side assert triggered
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
Compile with TORCH_USE_CUDA_DSA to enable device-side assertions.
我们翻译一下:
RuntimeError: CUDA error: device-side assert triggered
运行时错误:CUDA设备端断言被触发。
这表明在GPU设备上执行的代码中有断言失败。断言是一种错误检查,如果代码中的某个条件为假,则会引发断言失败。
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
CUDA核心(kernel)错误可能会在某些其他API调用中异步报告,因此下面的堆栈跟踪可能不正确。
由于CUDA操作可能是异步执行的,错误可能不会立即在引发它的确切位置被报告。这意味着错误消息中的堆栈跟踪可能不指向实际引发问题的位置。
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
为了调试,请考虑传递CUDA_LAUNCH_BLOCKING=1。
这是一个调试技巧。通过设置环境变量CUDA_LAUNCH_BLOCKING=1,可以使CUDA操作同步执行,这有助于准确地定位引发错误的代码行。
Compile with ‘TORCH_USE_CUDA_DSA’ to enable device-side assertions.
使用‘TORCH_USE_CUDA_DSA’编译以启用设备端断言。
这建议在编译PyTorch时启用设备端断言,这可以帮助开发者捕捉到在GPU上执行的代码中的问题。
解决方法
在线搜索解决方案:
我首先在网上搜索了这个问题的解决方案,发现许多网友建议错误可能是由于分类任务中训练数据标签超出了设定的类别数目所导致的。例如,如果设置了8个类别,但训练数据中的标签却包含了9,就会触发这个错误。此外,还需要注意一个常见的陷阱:即使标签从0开始计数,在PyTorch中使用0或负数作为类别标签也会导致错误。因此,如果类别标签从0开始,需要将所有类别标签加1以避免错误。
根据PyTorch的工作原理,它会扫描存放训练数据的train_path目录下每个文件夹(每个类别的图片都存放在自己的文件夹中),并将每个类别映射为一个数值。例如,如果有4个类别,类别标签将被映射为[0, 1, 2, 3]。在二分类问题中,标签会被映射为[0, 1],但在多分类问题中,标签的映射可能会不同,这有时会导致错误。
代码审查:
尽管我按照上述思路进行了修改,但问题依然存在。因此,我仔细检查了代码,最终发现问题并不在于标签与类别数目不匹配,而在于神经网络最后一层的设置有误。具体来说,输出层的设置需要与模型应该输出的类别数目一致。
在我的模型中,原本的代码是这样的:
self.outlayer = nn.Linear(256 * 1 * 1, 3) # 这是一个3分类问题的全连接层设置
但由于我面对的是5分类问题,我需要修改全连接层以反映正确的类别数目,修改后的代码如下:
self.outlayer = nn.Linear(256 * 1 * 1, 5) # 修改为5分类问题的全连接层设置
经过这次修改,错误得到了解决。
总结来说,解决这个问题需要仔细检查数据的标签处理以及神经网络模型的设置,确保它们与问题的实际需求相匹配。在调试过程中,对代码的每一个细节都进行仔细的审查是非常关键的。