YOLO 训练中“内存爆了”和“显存爆了”的区别与排查复盘
项目矿区安全检测 YOLO26 六类模型与单类别补标模型1. 背景这次我们在实验室 RTX 5090 机器上训练 6 个单类别补标辅助模型目标是用单类模型扫描全量数据集发现原始 6 类标签中的漏标候选。其中helmet / vest / tractor / slipper / smoking基本都有训练结果和best.pt但person训练失败只生成了args.yaml和空的weights目录没有results.csv、best.pt、last.pt。一开始容易误以为是“5090 显存不够”或者“模型训练失败”但查日志后发现真正原因是MemoryError EOFError: Ran out of input日志中还有关键线索train: Caching images (31.0GB RAM): 100% 20355/20355这说明问题不是 GPU 显存爆了而是 CPU 内存 RAM 被cacheram和 dataloader worker 吃满了。2. 一句话区分内存和显存分别干什么训练深度学习模型时机器主要有两类“容量资源”资源常见名称主要用途爆掉时常见表现CPU 内存RAM / 内存存图片缓存、解码后的图像、dataloader 队列、数据增强、Python 进程对象MemoryError、系统卡死、进程被杀、worker EOFGPU 显存VRAM / 显存模型参数、梯度、batch 张量、前向/反向中间特征图CUDA out of memory、torch.cuda.OutOfMemoryError简单理解模型真正计算主要在显存里跑。 图片读取、缓存、增强、排队主要吃内存。所以 RTX 5090 有 32GB 显存并不代表系统内存也够用。尤其 Windows 下多进程 dataloader 会额外放大内存压力。3. 本次真实案例person 单类为什么失败本次 person 单类训练参数大致是modelyolo26n.pt imgsz832 batch64 cacheram workers4 epochs100 patience25person 单类数据量最大训练集图片数约 20355 张。由于设置了--cache ramUltralytics 会在训练前尝试把图片缓存进内存。日志显示缓存到了31.0GB RAM缓存结束后程序继续启动 dataloader worker。Windows 下workers4会创建多个子进程涉及对象序列化和进程间传递内存压力继续上升最终报错MemoryError EOFError: Ran out of input因此 person 训练并不是在第几十轮崩掉而是基本还没开始正式训练就在构建训练数据管道时失败了。4. 为什么其他类别能训练而 person 不行单类模型的数据集是按“正样本 反例”构建的。类别不同正样本数量不同最终训练图片数也不同。person 类正样本最多因此构造出来的数据集最大。cacheram会把整个训练集缓存进内存所以 person 最容易爆 RAM。而helmet / vest / tractor / slipper / smoking的数据量相对更小或者虽然日志后期也出现了MemoryError但训练过程中已经产生了results.csv weights/best.pt weights/last.pt这说明这些类别至少已经完成了有效训练并保存了权重。person 则没有best.pt不能使用。5. cacheram 到底是什么cacheram的作用是把训练图片缓存到内存中。优点减少硬盘读取 提高训练吞吐 数据增强前读取更快缺点数据集越大占用内存越高 多 worker 时内存压力更大 Windows 多进程开销更明显 如果内存不足会在训练前或训练初期崩掉所以cacheram适合数据集较小 机器 RAM 很大 训练反复多轮读取同一批图片 磁盘很慢且内存明显充足不适合全量大数据集 图片分辨率高 Windows 多 worker 内存不确定 同机还有别人跑任务6. batch、imgsz、workers、cache 分别影响什么很多训练问题会被混在一起说“爆了”但不同参数影响的资源不同。6.1 batch 主要影响显存batch越大一次送进 GPU 的图片越多。影响显存占用上升 前向/反向中间特征图更多 训练吞吐可能更高 梯度估计更稳定如果报错是CUDA out of memory torch.cuda.OutOfMemoryError优先降batch 64 - 32 - 16 - 86.2 imgsz 同时影响显存和内存imgsz越大输入图片越大。影响显存上升因为特征图更大 内存上升因为解码/缓存后的图像更大 训练速度下降 小目标更容易保留细节小目标如smoking / slipper通常不建议轻易降太低。但如果部署侧固定832训练补标模型也最好保持832避免训练尺度和部署尺度不一致。6.3 workers 主要影响 CPU 内存和数据加载workers是 dataloader 子进程数量。影响workers 越多读图/增强并行度越高 但每个 worker 都有进程开销 Windows 下 worker 启动和对象序列化更吃内存如果是内存问题尤其 Windows 上优先改workers 4 - 2 - 0workers0最稳表示主进程自己加载数据速度可能慢但不容易因为多进程而炸。6.4 cache 主要影响 CPU 内存cacheram是这次 person 崩掉的直接诱因。如果 RAM 不够改cacheram - cacheFalse训练会慢一点但稳定很多。7. 如何判断是内存爆了还是显存爆了7.1 看报错关键词内存爆MemoryError EOFError: Ran out of input worker exited unexpectedly 系统变卡 进程突然消失显存爆CUDA out of memory torch.cuda.OutOfMemoryError Tried to allocate ... MiB GPU memory7.2 看日志阶段如果发生在Scanning labels Caching images Building dataloader 启动 workers更可能是 RAM / 数据加载问题。如果发生在Epoch 1/100 前向推理 反向传播 loss.backward optimizer.step更可能是显存问题。7.3 看监控工具显存看nvidia-smi重点看Memory-Usage GPU-Util内存看 Windows 任务管理器或者 PowerShellGet-CimInstance Win32_OperatingSystem | Select-Object TotalVisibleMemorySize,FreePhysicalMemory训练时如果显存还有空间但系统 RAM 快满并且日志出现MemoryError那就不是显存问题。8. 本次 person 补跑建议为了避免再次因为 RAM 崩掉person 单类建议这样补跑cd /d E:\yolo26-kuangqu\ultralytics-main conda activate ultralytics set CUDA_VISIBLE_DEVICES0 python tools\train_single_autolabel_model.py ^ --dataset-root datasets\single_class_autolabel_full_v1\person ^ --model yolo26n.pt ^ --epochs 100 ^ --imgsz 832 ^ --batch 32 ^ --device 0 ^ --workers 0 ^ --cache False ^ --patience 25 ^ --name single_person_autolabel_yolo26n_v13 logs_autolabel_single\train_single_person_v13.log 21为什么这样设cacheFalse不再把 20355 张图塞进 RAM workers0避免 Windows 多进程复制/序列化造成额外内存压力 batch32降低显存压力也更稳 imgsz832和部署侧固定输入保持一致 epochs100 patience25给足训练上限同时允许早停如果训练速度可以接受就不要再开cacheram。稳定比快更重要。9. 如果是显存爆应该怎么处理如果日志是CUDA out of memory处理顺序建议降 batch64 - 32 - 16 - 8确认没有别的任务占 GPUnvidia-smi必要时降低 imgsz832 - 768 - 640但小目标任务不建议一上来降 imgsz。smoking和slipper对分辨率敏感降太低可能召回明显下降。关闭不必要的可视化或大 batch 验证。如果使用更大模型例如m / l / x考虑换n / s先做补标器。10. 如果是内存爆应该怎么处理如果日志是MemoryError处理顺序建议关闭 RAM 缓存cacheram - cacheFalse降低 workersworkers4 - workers2 - workers0降低 batch。虽然 batch 主要吃显存但 batch 小一点时 dataloader 队列压力也会下降。不要一次训练太大的单类数据集。可以先抽样训练补标器再扫全量。补标器追求召回不一定每类都要用全量训练。如果必须 cache优先试cachedisk。cachedisk不像cacheram那样吃内存但会占磁盘空间适合磁盘空间充足、内存不足的机器。11. 为什么不能简单地说“5090 怎么还会爆”RTX 5090 强的是 GPU 显存和算力不代表整机 RAM 无限。这次问题发生在CPU RAM 缓存图片 Windows dataloader 多进程 Python 对象序列化这些都不是 GPU 显存能直接解决的。哪怕 5090 显存还有很多只要系统 RAM 被缓存图片吃满训练一样会失败。所以正确表达是5090 负责模型计算系统内存负责数据供给。 算力强不等于数据管道不会爆。12. 面试中可以怎么讲如果面试官问“你遇到过训练资源问题吗怎么排查”可以这样回答遇到过一次 YOLO 检测训练失败机器是 RTX 5090一开始容易怀疑是显存问题。但我没有直接降 batch而是先看日志。日志显示模型在正式训练前已经完成了Caching images占用了约 31GB RAM随后在启动 Windows dataloader worker 时出现MemoryError和EOFError。这说明瓶颈不是 GPU 显存而是 CPU 内存和数据加载管道。后来我把cacheram改成cacheFalse并把workers从 4 降到 0同时适当降低 batch。这样避免一次性把全量图片装进内存也避免 Windows 多进程序列化带来的额外内存开销。这个问题让我形成了一个排查习惯如果是CUDA out of memory优先看显存、batch、imgsz如果是MemoryError优先看 cache、workers、数据集大小和 RAM。这个回答的重点是不是只会说“降 batch” 而是能区分 GPU 计算瓶颈和 CPU 数据管道瓶颈 能从日志定位问题阶段 能给出有针对性的解决方案13. 本项目后续建议对于这类矿区安全检测项目数据集越来越大类别又包含小目标建议形成固定训练策略最终 6 类模型 优先保证 imgsz 和部署侧一致例如 832 batch 根据显存调 cache 默认 False除非明确确认 RAM 足够 单类补标模型 小目标类别可以多给 epoch 和 patience 数据特别大的 person 类不要 cacheram Windows