原帖连创建一个简单 CUDA 张量都失败,但这段创建代码本身不足以证明标签或索引越界:
RuntimeError: CUDA error: device-side assert triggered
先区分“会话已坏”与“新操作触发”
原题是在 Google Colab 创建 [1,2] 时看到断言,没有提供损失函数或词表索引。文章中常见的标签越界只是可能原因,不能据此补出原题根因。对这个场景,最有区分力的操作是全新运行时中的最小 CUDA 张量,而不是先改 batch_size。
CUDA 执行具有异步性,较早发生的断言可能在后续张量操作才被报告。已经触发设备断言的会话也可能继续报错。先重启 Colab 运行时,在任何 CUDA 操作前设置同步调试,再只运行最小检查:
import os
os.environ["CUDA_LAUNCH_BLOCKING"] = "1"
import sys
import torch
print("josh050608")
print("python/build:", sys.executable, torch.__version__, torch.version.cuda)
print("available:", torch.cuda.is_available())
t = torch.tensor([1, 2], device="cuda")
print("tensor:", t, t.device)
若全新会话中这段能运行,逐段恢复原来的数据处理和训练,记录第一个出错操作;不要从最后一次 print 或 .cpu() 推断根因。普通 Linux 终端也可用 CUDA_LAUNCH_BLOCKING=1 python train.py 启动调试。
若首次失败在分类损失前,检查 logits.shape[1] 与标签范围:类别索引必须满足 0 <= target < C,显式配置的 ignore_index 除外。若在 Embedding 或索引运算,核对索引是否小于词表/被索引维度长度。对同一小批数据在 CPU 重跑,通常能得到更直接的越界提示。
如果重启后仅创建张量就失败,才继续查运行时与驱动,而不是编造训练标签问题。修复后应再次从干净进程跑最小张量检查和首个训练批次;同步模式用于定位,调通后可移除以恢复性能。
把第一次失败缩到一个批次
若干净运行时的张量测试成功,按“取一批数据 → 模型前向 → 损失 → backward → step”逐段加回来。同步调试启用后,记录首次失败的操作以及那一批输入,后续重复出现的同一句断言通常不再提供新的根因证据。
对于单标签分类,下面是可以放在损失前的边界检查函数。logits 是模型实际输出,target 是同批标签,ignore_index 必须传入当前损失函数真实设置的值;下面用合成 CPU 数据展示好坏两组输入:
import torch
def check_class_indices(logits, target, ignore_index=-100):
if target.dtype != torch.long:
raise TypeError(f"类别索引应为 long,实际为 {target.dtype}")
classes = logits.shape[1]
selected = target[target != ignore_index]
bad = selected[(selected < 0) | (selected >= classes)]
print("logits/target:", logits.shape, target.shape)
print("classes/bad labels:", classes, bad[:10].tolist())
if bad.numel():
raise ValueError("标签超出当前输出类别范围")
logits = torch.randn(3, 2)
check_class_indices(logits, torch.tensor([0, 1, 0]))
try:
check_class_indices(logits, torch.tensor([0, 1, 2]))
except ValueError as exc:
print("caught before CUDA loss:", exc)
这个函数只覆盖“类别索引目标”这条路线;多标签概率目标、Embedding 输入或自定义 CUDA 算子需要核对各自约束。若是 Embedding,比较最大索引与 embedding.num_embeddings;若是图像索引,核对的应是被索引那一维,不能拿类别数代替。
CUDA_LAUNCH_BLOCKING=1 会让异步调用更接近真实失败点,但不能恢复已经损坏的 CUDA 会话,也不会修正数据。TORCH_USE_CUDA_DSA 涉及构建时支持,给已安装 wheel 临时加环境变量不等于重新编译出了断言信息。
当 CPU 小批次也失败,先修正它报告的标签或索引;当 CPU 通过、全新 CUDA 最小程序仍失败,再保留 torch 构建、驱动和设备信息检查运行环境。最终验证应从重启后的第一批开始,而不是继续在已断言的进程里尝试 .empty_cache()。
参考:原始求助帖;技术依据:PyTorch CUDA 语义(2.5)、PyTorch CUDA 环境变量(2.5)、CrossEntropyLoss(2.5)、Embedding(2.5)。