CUDA 显存碎片排查:显存空着,为什么还会 OOM

📅 2026/7/4 3:47:54
CUDA 显存碎片排查:显存空着,为什么还会 OOM
CUDA 显存碎片排查显存空着为什么还会 OOM训练或推理时经常看到一个现象监控显示还有显存但程序仍然 OOM。原因之一是显存碎片。深度学习框架通常有缓存分配器显存被分成不同块反复申请释放。如果可用显存不连续就可能无法满足一次大分配。显存 OOM 不等于总显存完全耗尽。排查时要区分已分配、已保留、缓存和碎片。一、先理解分配器视角flowchart TD A[GPU Memory] -- B[Allocated] A -- C[Reserved By Allocator] C -- D[Free Blocks] C -- E[Fragmented Blocks] B -- F[Tensors In Use]nvidia-smi看到的是进程占用PyTorch 里还要看 allocated 和 reserved。reserved 大不代表都被 tensor 使用。二、记录 PyTorch 显存指标import torch print(torch.cuda.memory_allocated() / 1024**2) print(torch.cuda.memory_reserved() / 1024**2) print(torch.cuda.max_memory_allocated() / 1024**2) print(torch.cuda.memory_summary())如果 reserved 明显高于 allocated可能存在缓存或碎片。注意不要在训练主循环里频繁empty_cache()它可能降低性能并不能根治分配模式问题。三、动态 shape 会加剧碎片NLP 训练中不同 batch 的序列长度变化会导致激活张量大小不断变化。频繁的大块申请释放容易产生碎片。mitigation: bucket_by_sequence_length: true fixed_max_length_for_eval: true gradient_checkpointing: optional reduce_batch_size_variance: true按长度分桶通常比盲目减小 batch 更稳。它减少 shape 抖动也改善 padding 浪费。四、定位要结合时间线显存碎片问题常在跑了一段时间后出现。要记录每个 step 的 allocated、reserved、batch shape 和是否发生 OOM。step_log: step seq_len batch_size allocated_mb reserved_mb max_allocated_mb如果某些极长 batch 后 reserved 持续高企就要检查数据采样和 batch 构造策略。也要记录是否使用混合精度、梯度累积和 checkpoint。它们都会改变激活保存方式和分配模式。只看 batch size往往不足以解释显存曲线。五、总结CUDA OOM 不一定是总显存不够也可能是分配器缓存和碎片导致大块显存申请失败。排查时看 allocated、reserved、memory summary并结合 batch shape 时间线。显存优化不能只靠减 batch。稳定 shape、长度分桶、合理 checkpoint 和记录分配行为才是更可解释的处理方式。排查显存问题时保留时间线比保留最后一条 OOM 日志更有价值。如果能把数据 batch 的长度分布也记录下来很多看似随机的 OOM 会变得可解释。