# Experiment B Performance Tuning ## 背景 本文档基于 `2026-03-31` 对实验 B 当前正式训练的实时观测整理,目标是回答: 1. 当前系统资源到底卡在哪里 2. 哪些参数最值得优先调整 3. 怎样在不破坏现有可跑性的前提下,尽量提升训练速度 当前训练实例: - 训练日志:`runs/logs/tomato-exp-b-attr_20260331-192847.log` - 输出目录:`runs/mid/qwen3_5_35b_a3b_exp_b_attr/v1-20260331-192847` - 当前启动时的关键降载参数: - `DATASET_NUM_PROC=1` - `DATALOADER_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 的时间主要消耗在两段: 1. 数据映射 / tokenization 阶段很长 2. 进入训练后,GPU 利用率仍偏低 同时,日志里还能看到两个重要事实: - 当前使用的是 `--attention_backend unfused` - 参数对象里实际 `sequence_parallel=False` 这意味着: - 训练吞吐已经天然比更激进的 fused/flash 路线慢 - 不能把当前性能预期建立在“高级并行优化已生效”的假设上 ## 主要瓶颈判断 基于当前观测,实验 B 的性能问题优先级大致如下: 1. 预处理阶段过慢,且并发一高就有稳定性风险 2. 训练阶段 GPU 显存占用中等,但算力利用率偏低 3. 当前批大小和重计算策略偏保守,更像“先保跑通”,不是“先榨吞吐” 4. 现有 `unfused` attention backend 本身限制了吞吐上限 不是主要瓶颈的项: - 机器总内存容量 - 磁盘 I/O - 整机 CPU 总量 ## 提速建议 以下建议按优先级排序。 ### P0:先把“稳定跑通”和“性能调优”分成两套参数 当前这轮参数适合保命,不适合作为长期最快配置。 建议保留两套启动配置: - `safe` 配置 - `DATASET_NUM_PROC=1` - `DATALOADER_NUM_WORKERS=2` - `fast` 配置 - 从 `DATASET_NUM_PROC=2` - `DATALOADER_NUM_WORKERS=4` - 开始逐步压测 理由: - 现在最清楚的事实是:预处理并发拉高后,实验 B 曾经直接被系统杀掉。 - 但一味维持 `1/2` 组合,会显著拖慢数据准备。 推荐做法: 1. 先用 `safe` 配置跑通一次完整训练 2. 再单独开小样本性能压测,把 `dataset_num_proc` 和 `dataloader_num_workers` 逐步抬高 3. 只要出现明显 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=4` - `tensor_model_parallel_size=1` - `pipeline_model_parallel_size=1` 这说明当前主要是 EP 路线。 建议: - 对 `expert_model_parallel_size=4` 和更保守配置做小样本性能对照 - 重点观察 step time、GPU util 和通信开销 原因: - 当前 GPU 利用率不高,可能有一部分时间耗在 MoE 路由和通信上 - 这类瓶颈通常不能只靠加 dataloader 解决 这项不建议直接在正式训练上改,先做 benchmark。 ### P6:处理 swap 已满的问题 虽然当前物理内存还很多,但 swap 已满不是健康信号。 建议: - 正式训练前确认没有残留的大进程长期占内存 - 定期清理历史残留的训练/推理进程 - 把“预处理高并发压测”与“正式训练”分开,避免训练时叠加系统脏状态 如果后续还出现: - 数据映射阶段突然变慢 - 训练被 `SIGKILL` 应优先排查内存换出和宿主机资源保护,而不是先怀疑模型参数。 ## 推荐调优顺序 建议按下面顺序做,不要一次改太多: 1. 先用当前 `safe` 配置完整跑通实验 B 2. 抽离数据缓存预构建步骤 3. 压测 `MICRO_BATCH_SIZE=5/6` 4. 压测较轻的 `recompute` 配置 5. 压测更激进的 dataloader / dataset 并发 6. 再评估 `attention backend` 和 `expert_model_parallel_size` ## 最值得先做的三件事 如果只做最有收益的三项,优先建议: 1. 把数据缓存预构建独立出来,避免每次重试都重复长时间 `Map` 2. 增大 `MICRO_BATCH_SIZE`,把剩余显存换成吞吐 3. 在稳定跑通后,降低重计算强度,减少“用时间换显存” ## 一句话结论 当前实验 B 的主要问题不是机器不够强,而是训练配置仍偏“保守保命型”。 这台机器的瓶颈不在磁盘和总内存,当前最值得利用的性能空间主要在: - 更合理的数据缓存策略 - 更大的 batch - 更少的重计算 - 更高效的 attention backend