CUDA运行时错误(59):设备端断言触发。

87
THCudaCheck FAIL file=/opt/conda/conda-bld/pytorch_1524584710464/work/aten/src/THC/generated/../generic/THCTensorMathPointwise.cu line=265 error=59 : device-side assert triggered
Traceback (most recent call last):
  File "main.py", line 109, in <module>
    train(loader_train, model, criterion, optimizer)
  File "main.py", line 54, in train
    optimizer.step()
  File "/usr/local/anaconda35/lib/python3.6/site-packages/torch/optim/sgd.py", line 93, in step
    d_p.add_(weight_decay, p.data)
RuntimeError: cuda runtime error (59) : device-side assert triggered at /opt/conda/conda-bld/pytorch_1524584710464/work/aten/src/THC/generated/../generic/THCTensorMathPointwise.cu:265

我该如何解决这个错误?


6
尝试使用CUDA_LAUNCH_BLOCKING=1 python your_script.py来运行您的脚本,以获得更准确的堆栈跟踪。 - McLawrence
运行时使用CUDA_LAUNCH...=1后,我遇到了以下错误:/opt/conda/.../THCUNN/ClassNLLCriterion.cu:105: void cunn_ClassNLLCriterion_updateOutput_kernel(Dtype *, Dtype *, Dtype *, long *, Dtype *, int, int, int, int, long) [with Dtype = float, Acctype = float]: block: [0,0,0], thread: [0,0,0] Assertion t >= 0 && t < n_classes failed. 这个错误会出现大约20次。然后跟踪信息如下:RuntimeError: cuda runtime error (59) : device-side assert triggered at /opt/conda/conda-bld/pytorch_1524580978845/work/aten/src/THCUNN/generic/ClassNLLCriterion.cu:116 如何解决? - saichand
12
你的目标标签存在错误:t >= 0 && t < n_classes。请打印出你的标签并确保它们为正数且小于你最后一层输出的数量。 - McLawrence
n_classes 应该与最后一层的输出相同。这样对吗? - saichand
没错。你的目标可能设定得太高了。 - McLawrence
@McLawrence,我的错误指向 return self.apply(lambda x: x.to(device), *keys) 但是如果我不使用to(device)选项,则会显示CUDA(x所需的)和此情况下实际x的cpu之间的设备不匹配错误。 - Kanishk Mair
12个回答

120

这通常是一个索引问题。

例如,如果您的真实标签从1开始:

target = [1,2,3,4,5]

那么您应该减去每个标签的1,以便:

target = [0,1,2,3,4]

3
我可以确认,在我的情况下,这也是错误的原因。例如,有效的文本标签已被转换为0..n-1(n为类数)。然而,NaN值被转换为-1,这使其失控了。 - Christian
2
@Rainy,你能详细解释一下“ground truth label starts at 1”吗?你的意思是什么?我了解到标签是从1到5,并且为了克服错误,错误中的第一个值应该为零。我是对的吗? - Kunj Mehta
@KunjMehta,不仅第一个值应该是零。类索引应该从零开始。例如,对于6个类,索引值应该从0到5。 - Chandra
我按照您提供的设置,但仍然出现错误。 - Nihat

75

一般情况下,遇到 cuda runtime error 时,推荐使用 CUDA_LAUNCH_BLOCKING=1 标志重新运行程序以获取准确的堆栈跟踪。

在您的具体情况中,您的数据目标值过高(或过低)超出了指定类别数。


14
除此之外,一旦您获得了更准确的堆栈跟踪并确定了问题所在,您可以将张量移动到 CPU 上。将张量移动到 CPU 上将提供更详细的错误信息。将 CUDA_LAUNCH_BLOCKING=1 与将张量移动到 CPU 结合使用是我解决一个让我花了三天时间的问题的唯一方法。 - Eric Wiener
如何在 Kaggle 内核上运行此程序? - curiouscheese

17

当我运行BertModel.from_pretrained('bert-base-uncased')时,遇到了这个错误。当错误信息变成 'IndexError: index out of range in self' 时,我通过切换到CPU找到了解决方法。这让我想起了这篇文章。解决方案是将句子截断至长度512。


很好的建议。使用CPU作为设备所导致的错误非常明显;我写了一个非常基本的索引错误。 - Mew

10

导致“CUDA错误:设备端触发断言”RuntimeError的一种方法是使用具有超出维度索引的list对GPU torch.Tensor进行索引。

因此,这段代码会引发一个IndexError,并显示消息“IndexError:index 3 is out of bounds for dimension 0 with size 3”,而不是CUDA错误。

data = torch.randn((3,10), device=torch.device("cuda"))
data[3,:]

与此相反,这会引发CUDA“设备端触发断言”的RuntimeError

data = torch.randn((3,10), device=torch.device("cuda"))
indices = [1,3]
data[indices,:]

这可能意味着,在类别标签的情况下,如@Rainy所说,当标签从1开始而不是0时,最终类别标签(即label == num_classes)会导致错误。此外,当设备为"cpu"时,会抛出IndexError错误,例如第一个代码片段抛出的错误。

4
我发现当我使用无效值的标签时,会出现此错误。

即使在我的情况下,问题也出在标签的无效值上,因为我忘记在最后一层中加入激活函数。谢谢! - Vinod Kumar Chauhan

2
当我实例输入令牌的长度大于模型最大长度且输入长度大于max_output_length预测参数时,我遇到了这个问题。

你的回答可以通过提供更多支持性信息来改进。请编辑以添加更多细节,例如引用或文档,以便他人可以确认你的回答是否正确。你可以在帮助中心找到有关如何编写好的答案的更多信息。 - Community

2

如果您首先切换到CPU,可以更详细地了解此错误。一旦切换到CPU,它将显示确切的错误,这很可能与索引问题有关,例如IndexError:在我的情况下,目标2超出范围,并且可能与您的情况有关。问题是“您当前使用多少类以及输出的形状是什么?”,您可以像这样找到类

max(train_labels)
min(train_labels)

在我的情况下,这给了我2和0,问题是由于缺少1索引引起的,所以一个快速的hack是将所有的2替换为1,可以通过以下代码实现:

train_=train.copy()
train_['label'] =train_['label'].replace(2,1)

然后您运行相同的代码并查看结果,它应该可以正常工作。

class NDataset(torch.utils.data.Dataset):
    def __init__(self, encodings, labels):
        self.encodings = encodings
        self.labels = labels

    def __getitem__(self, idx):
        item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
        item['labels'] = torch.tensor(self.labels[idx])
        return item

    def __len__(self):
        return len(self.labels)

train_dataset = NDataset(train_encodings, train_labels)
val_dataset = NDataset(val_encodings, val_labels)
test_dataset = NDataset(test_encodings, test_labels)

1
另一种可能出现这种情况的情形是:您正在使用比最后一层所期望的类别更多的类别对数据集进行训练。这是另一种意外的索引情况。

0

这也可能是由于模型输入数据中存在nan值引起的。解决此问题的一种简单方法是在运行时将任何出现的nan值转换为零:

batch_data = batch_data[batch_data != batch_data] = 0

0

希望你的问题已经解决了,但我遇到了这个问题并花了近两个小时来解决它,所以我会在这里为像我一样的人解释问题和解决方法。
我的问题是由于类标签引起的。
我的项目是关于情感分析的,有三个类别,所以我用值-1、0、1(输出层中的3个节点)标记数据集,这导致了我的问题!
因此,我重新标记了数据集,使用值0、1、2,并解决了问题。重要的是要从0开始标记样本(PyTorch使用索引作为类标签,所以你应该小心)。
对于那些遇到错误说设置CUDA_LAUNCH_BLOCKING = 1的人,你应该在导入PyTorch之前使用这个命令:os.environ['CUDA_LAUNCH_BLOCKING'] = "1",如果你遇到同样的错误(没有更多关于错误的信息),你应该通过CPU运行脚本,然后再试一次(这次你可能会得到新的问题信息)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接