指南: 故障排查 (TROUBLESHOOTING.md)
本指南旨在帮助您快速诊断和解决在使用本训练框架时可能遇到的常见问题.
问题 1: CUDA out of memory (显存不足)
这是训练深度学习模型时最常见的错误之一.
可能的原因及解决方案:
-
批量大小 (
batch_size) 过大: 这是最常见的原因. 模型、梯度和优化器状态都需要存储在显存中, 较大的批量会消耗更多显存.- 解决方案: 在配置中减小
training.batch_size的值. 例如, 从256减到128或64.
- 解决方案: 在配置中减小
-
模型过大: 模型的参数量直接决定了其占用的显存.
- 解决方案: 尝试使用层数更少 (
num_layers) 或隐藏层维度更小 (hidden_size) 的模型配置.
- 解决方案: 尝试使用层数更少 (
-
未开启混合精度训练 (AMP): AMP 可以显著减少显存占用, 尤其是在使用像 V100 或 A100 这样的 Tensor Core GPU 时.
- 解决方案: 确保
optimization.use_amp设置为true(或在命令行中不要使用--no-optimization-use-amp). 这是默认开启的.
- 解决方案: 确保
-
梯度累积 (Gradient Accumulation): (注: 此功能需手动实现) 如果您不能再减小批量大小, 可以考虑使用梯度累积. 它通过多次前向/反向传播来累积梯度, 然后执行一次优化器步骤, 从而在不增加显存的情况下模拟更大的批量.
问题 2: DDP (分布式) 相关错误
分布式训练的配置较为复杂, 容易出错.
常见错误 1: DDP Misconfiguration: world_size is X, but ... insufficient GPUs
- 原因: 框架检测到您希望使用的进程数 (
world_size) 与可用的 GPU 数量不匹配. - 解决方案:
- 检查您的
DistributedConfig或环境变量GPUS_PER_NODE是否设置正确. - 运行
nvidia-smi确认您的机器上有多少可用的 GPU. world_size应该等于num_nodes * gpus_per_node.
- 检查您的
常见错误 2: 训练进程卡死 (Hangs)
- 原因: 这通常是由于某个进程没有参与到集体通信操作(如
all_reduce或barrier)中, 导致其他进程无限期等待. 可能是某个进程提前崩溃, 或者不同进程执行了不同的代码路径. - 解决方案:
- 检查日志: 查看每个
rank的日志文件, 找出是否有某个进程在其他进程卡住之前就抛出了错误. - 网络问题: 在多节点环境中, 确保节点之间的网络连接是畅通的, 特别是
MASTER_ADDR和MASTER_PORT指定的端口没有被防火墙阻塞. - 代码分支: 确保在所有 DDP 进程中, 参与分布式操作的代码路径是一致的. 避免只在
rank == 0的进程中执行可能影响其他进程的逻辑(除非该逻辑被if self.rank == 0:妥善保护).
- 检查日志: 查看每个
问题 3: 性能不理想 / GPU 利用率低
可能的原因及解决方案:
-
数据加载瓶颈: CPU 准备数据的时间超过了 GPU 计算的时间.
- 解决方案:
- 增加
optimization.num_workers的值, 以使用更多进程来并行加载数据. 一个经验法则是设置为您 CPU 核心数的一半左右. - 确保
optimization.pin_memory设置为true, 这可以加速数据从 CPU 到 GPU 的传输.
- 增加
- 解决方案:
-
未开启
torch.compile: 在支持的硬件和 PyTorch 版本上,torch.compile可以显著提速.- 解决方案: 确保
optimization.use_compile设置为true(或不要使用--no-optimization-use-compile命令行标志).
- 解决方案: 确保
-
频繁的 CPU-GPU 同步: 例如, 在训练循环中频繁调用
.item()或打印张量.- 解决方案: 减少不必要的同步操作. 框架的日志记录是经过优化的, 只在特定的间隔 (
log_interval) 打印, 并且只在rank 0进程中进行.
- 解决方案: 减少不必要的同步操作. 框架的日志记录是经过优化的, 只在特定的间隔 (
问题 4: 检查点加载失败或无效
常见错误: Error(s) in loading state_dict for ...: Missing key(s) in state_dict: ...
- 原因: 您尝试加载的检查点中的模型结构与当前代码中定义的模型结构不匹配.
- 解决方案:
- 确保您在恢复训练时, 使用的模型配置 (
ModelConfig) 与保存该检查点时的配置完全相同. - 如果您确实想加载一个结构不同的模型(例如, 进行迁移学习), 您可能需要手动编写代码来加载匹配的权重部分, 而不是直接使用
load_state_dict.
- 确保您在恢复训练时, 使用的模型配置 (
常见错误: 恢复训练后, 效果与之前不符
- 原因: 可能只加载了模型的权重, 而没有加载优化器、学习率调度器和随机数生成器的状态.
- 解决方案: 确保您的
CheckpointManager正确保存和加载了所有相关状态. 本框架的CheckpointManager已经处理了这些, 所以通常只要使用--checkpoint-resume-from-checkpoint参数即可正确恢复.
问题 5: MoE (Mixture of Experts) 相关问题
常见错误 1: MoE 训练收敛困难或性能不佳
- 原因: MoE 模型的训练可能比传统模型更具挑战性, 不合理的
top_k设置或专家利用率不均衡都可能导致收敛问题. - 解决方案:
- 调整
top_k: 尝试不同的top_k值. 过大的top_k会增加计算量, 而过小的top_k可能限制模型的表达能力. - 负载均衡损失 (Load Balancing Loss): 考虑在损失函数中添加一个负载均衡损失项, 以鼓励所有专家被均匀利用. 这有助于避免某些专家被过度使用而其他专家被闲置的情况.
- 门控网络初始化: 确保门控网络的初始化有助于有效的专家路由.
- 调整
常见错误 2: MoE 训练时出现 NaN 或 Inf 值
- 原因: 这通常是由于数值不稳定造成的, 尤其是在门控网络的
softmax输出或专家 MLP 的计算中. - 解决方案:
- 检查门控网络输出: 确保门控网络的 logits 不会过大或过小, 导致
softmax出现数值问题. - 调整学习率: 尝试减小学习率, 过大的学习率可能导致训练不稳定.
- 梯度裁剪: 确保梯度裁剪 (
training.gradient_clip_val) 已启用并设置合理. - 检查专家 MLP: 确保专家 MLP 内部的计算没有导致数值溢出.
- 检查门控网络输出: 确保门控网络的 logits 不会过大或过小, 导致
问题 6: 命令行参数解析错误
常见错误: 运行 train.py 时出现 unrecognized arguments 错误
- 原因: 您在命令行中提供的参数名称或格式与框架期望的不匹配.
- 解决方案:
- 检查参数名称: 确保您使用的参数名称符合
--<配置组名称>-<参数名称>的约定(例如,--model-hidden-size,--training-epochs). - 布尔参数格式: 布尔参数(
True/False)不应带值. 如果参数默认值为False, 使用--<参数名>启用;如果默认值为True, 使用--no-<参数名>禁用. 例如, 启用use_moe使用--model-use-moe, 禁用use_compile使用--no-optimization-use-compile. - 查看帮助: 运行
python -m llm.training.train --help查看所有可用的命令行参数及其正确的格式.
- 检查参数名称: 确保您使用的参数名称符合