Experiment B Performance Tuning
背景
本文档基于 2026-03-31 对实验 B 当前正式训练的实时观测整理,目标是回答:
- 当前系统资源到底卡在哪里
- 哪些参数最值得优先调整
- 怎样在不破坏现有可跑性的前提下,尽量提升训练速度
当前训练实例:
- 训练日志:
runs/logs/tomato-exp-b-attr_20260331-192847.log - 输出目录:
runs/mid/qwen3_5_35b_a3b_exp_b_attr/v1-20260331-192847 - 当前启动时的关键降载参数:
DATASET_NUM_PROC=1DATALOADER_NUM_WORKERS=2
说明:
- 这两个参数不是为了提速,而是为了绕过上一轮实验 B 在数据映射阶段被
SIGKILL的问题。 - 当前这轮已经成功越过上一轮失败位置,并进入正式
Train阶段。
实时观测
1. GPU
观测时刻的 nvidia-smi:
- GPU 显存占用约
33.9 GiB ~ 35.1 GiB / 49.1 GiB - GPU 利用率约
19% ~ 27% - 功耗约
95W ~ 115W
补充观测:
nvidia-smi dmon连续采样期间,显存保持高占用,但sm利用率瞬时值很低。- 这说明模型已经装载完成,但算力并没有持续吃满。
结论:
- 当前不是“显存不够”,而是“显存还有余量,但计算吞吐没有被充分压满”。
- 对 RTX 6000 Ada 来说,当前功耗和利用率都偏保守,明显还有提速空间。
2. CPU
观测时刻的系统级 CPU:
112核机器整体idle大约90%iowait约1%
训练相关进程:
- 4 个主要训练 worker 的单进程 CPU 大约都在
96%左右
结论:
- 机器总 CPU 资源非常充足。
- 当前不是整机 CPU 不够,而是训练进程只吃到了少量核,整体 CPU 远未成为上限。
3. 内存与 Swap
观测时刻:
- 物理内存总量约
1.0 TiB available约867 GiB- swap
15 GiB已满
结论:
- 内存容量本身完全不是问题。
- 但 swap 已满说明机器历史上发生过明显的内存换出,这对训练稳定性是个风险信号。
- 上一轮实验 B 在数据映射阶段被
SIGKILL,与预处理阶段资源压力过高是吻合的。
4. 磁盘 I/O
iostat 观测结果:
- CPU
iowait很低 - NVMe 利用率很低,吞吐量也不高
结论:
- 当前不是磁盘带宽瓶颈。
- 训练速度慢,主要不是因为数据文件读不动。
5. 训练阶段特征
从日志看,实验 B 的时间主要消耗在两段:
- 数据映射 / tokenization 阶段很长
- 进入训练后,GPU 利用率仍偏低
同时,日志里还能看到两个重要事实:
- 当前使用的是
--attention_backend unfused - 参数对象里实际
sequence_parallel=False
这意味着:
- 训练吞吐已经天然比更激进的 fused/flash 路线慢
- 不能把当前性能预期建立在“高级并行优化已生效”的假设上
主要瓶颈判断
基于当前观测,实验 B 的性能问题优先级大致如下:
- 预处理阶段过慢,且并发一高就有稳定性风险
- 训练阶段 GPU 显存占用中等,但算力利用率偏低
- 当前批大小和重计算策略偏保守,更像“先保跑通”,不是“先榨吞吐”
- 现有
unfusedattention backend 本身限制了吞吐上限
不是主要瓶颈的项:
- 机器总内存容量
- 磁盘 I/O
- 整机 CPU 总量
提速建议
以下建议按优先级排序。
P0:先把“稳定跑通”和“性能调优”分成两套参数
当前这轮参数适合保命,不适合作为长期最快配置。
建议保留两套启动配置:
safe配置DATASET_NUM_PROC=1DATALOADER_NUM_WORKERS=2
fast配置- 从
DATASET_NUM_PROC=2 DATALOADER_NUM_WORKERS=4- 开始逐步压测
- 从
理由:
- 现在最清楚的事实是:预处理并发拉高后,实验 B 曾经直接被系统杀掉。
- 但一味维持
1/2组合,会显著拖慢数据准备。
推荐做法:
- 先用
safe配置跑通一次完整训练 - 再单独开小样本性能压测,把
dataset_num_proc和dataloader_num_workers逐步抬高 - 只要出现明显 swap 抖动或再次
SIGKILL,立即回退
P1:把数据缓存预构建为独立步骤
当前训练把“数据准备”和“正式训练”绑在同一次进程里,这会让每次重试都重复走长时间 Map。
建议:
- 增加一个独立的“数据缓存预构建”步骤
- 在正式训练前先把 train/val 数据的 tokenization 和缓存文件准备好
- 正式训练只消费缓存
价值:
- 可以把最不稳定、最容易触发
SIGKILL的阶段前置 - 训练重试时不必重复长时间
Map - 这通常是当前最容易拿到的真实提速项
P2:优先尝试增大 MICRO_BATCH_SIZE
当前 GPU 显存大约只占到了 34~35 GiB / 49 GiB,每卡仍有十几 GiB 余量。
建议从小步试探:
- 先试
MICRO_BATCH_SIZE=5 - 再试
MICRO_BATCH_SIZE=6 - 同步调整
GLOBAL_BATCH_SIZE
推荐原则:
- 维持梯度累积逻辑清晰
- 每次只改一个量
- 观察显存、step time、是否出现 OOM
理由:
- 当前显存没打满
- 但 GPU 算力利用率偏低
- 典型原因之一就是每步喂给 GPU 的活太小
这是最可能直接提升训练吞吐的参数。
P3:减少重计算强度
当前配置:
--recompute_granularity full--recompute_method uniform--recompute_num_layers 1
在显存还有余量的前提下,建议做对照试验:
- 降低
recompute范围 - 或直接尝试关闭部分重计算
理由:
- 重计算本质上是“用时间换显存”
- 现在更像是时间更紧,而不是显存更紧
建议:
- 先保留当前配置跑通一版
- 之后做一组短跑 benchmark,比对 step time 和显存峰值
P4:检查 attention backend
当前是:
--attention_backend unfused
这通常意味着:
- 兼容性更稳
- 吞吐更差
建议:
- 在不影响稳定性的前提下,继续修复 / 验证更快的 attention backend
- 如果后续能恢复到更高效的 fused/flash 路线,训练速度会有明显提升
这项的潜在收益很大,但风险也高,所以优先级放在批大小和重计算之后。
P5:重新评估 expert_model_parallel_size
当前配置:
expert_model_parallel_size=4tensor_model_parallel_size=1pipeline_model_parallel_size=1
这说明当前主要是 EP 路线。
建议:
- 对
expert_model_parallel_size=4和更保守配置做小样本性能对照 - 重点观察 step time、GPU util 和通信开销
原因:
- 当前 GPU 利用率不高,可能有一部分时间耗在 MoE 路由和通信上
- 这类瓶颈通常不能只靠加 dataloader 解决
这项不建议直接在正式训练上改,先做 benchmark。
P6:处理 swap 已满的问题
虽然当前物理内存还很多,但 swap 已满不是健康信号。
建议:
- 正式训练前确认没有残留的大进程长期占内存
- 定期清理历史残留的训练/推理进程
- 把“预处理高并发压测”与“正式训练”分开,避免训练时叠加系统脏状态
如果后续还出现:
- 数据映射阶段突然变慢
- 训练被
SIGKILL
应优先排查内存换出和宿主机资源保护,而不是先怀疑模型参数。
推荐调优顺序
建议按下面顺序做,不要一次改太多:
- 先用当前
safe配置完整跑通实验 B - 抽离数据缓存预构建步骤
- 压测
MICRO_BATCH_SIZE=5/6 - 压测较轻的
recompute配置 - 压测更激进的 dataloader / dataset 并发
- 再评估
attention backend和expert_model_parallel_size
最值得先做的三件事
如果只做最有收益的三项,优先建议:
- 把数据缓存预构建独立出来,避免每次重试都重复长时间
Map - 增大
MICRO_BATCH_SIZE,把剩余显存换成吞吐 - 在稳定跑通后,降低重计算强度,减少“用时间换显存”
一句话结论
当前实验 B 的主要问题不是机器不够强,而是训练配置仍偏“保守保命型”。
这台机器的瓶颈不在磁盘和总内存,当前最值得利用的性能空间主要在:
- 更合理的数据缓存策略
- 更大的 batch
- 更少的重计算
- 更高效的 attention backend