docs: T17 process-per-GPU results — measured throughput-neutral

Records the key empirical finding: process-per-GPU is statistically identical
to thread-per-GPU at this scale (thread 5.27x vs proc 5.31x @8, <1% noise; all
8 GPUs 95-99% util). The residual ~5.3x@8 non-linearity is the NCCL/PCIe
communication wall, NOT single-CUDA-context launch/cuBLAS serialization as the
old KI-5/T11 note speculated — measurement falsifies that hypothesis (same
methodology as T11 falsifying "bucket the all-reduce"). Correctness all green:
proc==thread loss 1.5e-7, cross-rank 1.2e-7, full regression + xserv md5
b04fc9f9 identical. Closes the process-per-GPU backlog item (measured no-op);
default training path unchanged. evolution.md Infra row + README T17 row +
known-issues entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-18 18:03:14 +08:00
parent 4abb17383a
commit 71b0a1621f
4 changed files with 89 additions and 11 deletions

View File

@@ -13,6 +13,26 @@ _(KI-1 fixed in T10. KI-5 fixed in T11. KI-2 fixed in T12. **KI-3激活重计
## Fixed
### process-per-GPUtorchrun 式独立 CUDA context— `CLOSED / 实测负结果` (T17)
- **背景**KI-5T11修掉 per-op `cudaMalloc` 串行后8 卡 scaling 从 ~1.3× 恢复到 **~5×@8**,但残留 ~5×@8 非完美线性。T11 doc / KI-5「残留」推测下一步是 **process-per-GPU**(每 rank 独立进程 + 独立 CUDA contexttorchrun 式——理由是「N rank 线程共享单 CUDA primary contextkernel-launch/cuBLAS 仍在 context 级串行」。**T17 把这条 torchrun 式链路落地并实测,证伪了该推测。**
- **实现([docs/16-process-per-gpu.md](16-process-per-gpu.md)**`xtrain-distributed``proc.rs`——`launch_processes` 每卡 spawn 一个 worker 进程re-exec current_exe + `XTRAIN_{RANK,WORLD,LOCAL_RANK,NCCL_ID}` env**launcher 一次性铸 `ncclUniqueId` 后 hex 编码注入子进程 env**(无共享 FS/TCP、无轮询、无竞态——id 在子进程出生前就原子就绪worker 读 env → bind device独立 CUDA context`DdpContext::init` + `build_model` + `train_rank` **全部复用 T8 零改动**。新 `train_ddp_mp` bin + `ddp_proc` test**保留 thread-per-GPU 旧路径**(回归 baseline。scope=process-per-GPU onlyZeRO-1 用户 drop
- **正确性(全绿,无回归)**proc vs 单卡 loss `5.67e-7`、**proc vs thread-per-GPU `1.5e-7`**(两路数值同量级)、跨 rank `1.19e-7`<1e-6全回归套 `--test-threads=1` 全绿 + **xserv 闭环 v3 重导 md5 逐位一致 `b04fc9f9`**T17 不碰任何数值路径)。
- **实测结果关键dash5 8× RTX 5090, dim384 per-rank batch32 seq256, steady-state**
| world | thread-per-GPU (`train_ddp`) | speedup | process-per-GPU (`train_ddp_mp`) | speedup |
|---|---|---|---|---|
| 1 | 93257 | 1.00× | 92952 | 1.00× |
| 2 | 149747 | 1.61× | 148809 | 1.60× |
| 4 | 278276 | 2.98× | 273308 | 2.94× |
| 8 | **491360** | **5.27×** | **493128** | **5.31×** |
world=8 各重复 2 thread 493671/493292proc 491102/494123——**两路差异 <1%落在噪声内**。)
- **诊断证伪原推测**process-per-GPU world=8 跑时 `nvidia-smi` 抽样 **8 卡全部 9599% util**每卡 ~23GB)——GPU **已 compute-bound 喂满、非串行空转**KI-512/8 在忙的串行病 T11 allocator 已治好)。8 卡满载却仍只 5.3× 缺的 ~35% 吞吐去向**每步 grad all-reduce + 本机 PCIe-only 拓扑在 8 rank 下的通信开销**T11 早点明的「~7% all-reduce + PCIe 余量那一层8 卡放大换独立 context 不动这一层。**结论本尺度dim3841024单机 8× PCIe RTX 5090残留非线性是通信/拓扑墙不是 launch 模型**——要再逼近线性须动 all-reduce overlap / NVLink 互联非本尺度优先)。
- **方法论一致**T11 实测证伪分桶 all-reduce」、T17 实测证伪process-per-GPU 解残留串行」——两次都靠 measure 推翻假设而非硬上profile/measure-first)。**净价值**落地 torchrun process-per-GPU 标准链路项目本职学训练全栈」)+ 把这个误导性 backlog **实测钉死关闭**。**默认训练路径不变**thread-per-GPUprocess-per-GPU 作并列可选路径留档
- **commit** T17 提交链`distributed: process-per-GPU launcher + worker` / `distributed: train_ddp_mp bin` / `test: process-per-GPU DDP correctness` / 设计文档 `docs: Phase T17 — process-per-GPU DDP design`)。
---
### KI-3 · 激活重计算gradient checkpointing— `FIXED` (T13)
- **触发点v8 surfaced**容量轴放大到 dim1024核心 ~210M+测是否 capacity-limitedautograd tape 为反向保存所有中间激活激活显存随 dim 线性增长——dim768 bf16 batch32 31.1GBT12 甜点区**dim1024 batch32 再次 OOM**实测撞 32100/32607MiB `OutOfMemory`)。
- **设计per-block gradient checkpointingopt-in[docs/12-activation-recompute.md](12-activation-recompute.md)**新增 `xtrain_autodiff::checkpoint(segment_fn, input, params)` 高阶原语类比 `torch.utils.checkpoint`)。**前向** input/params detach 成局部 leaf `segment_fn`只取输出值局部 tape 立即 drop 段内激活释放不留在外层 tapecheckpoint 节点 parents=[input, ..params]。**反向**从保存的 input + 未变的 param 值重跑 `segment_fn` 重建局部 tape用上游 grad seed`Var::backward_seeded`新增——段输出非标量回传恢复的 input/param 梯度 push 给真 parents局部 tape drop 重算激活释放模型每个 transformer block 前向用它包裹`--recompute` flag默认关)。切粒度 = block
@@ -68,7 +88,7 @@ _(KI-1 fixed in T10. KI-5 fixed in T11. KI-2 fixed in T12. **KI-3激活重计
**单卡 40226→92638 tok/s (~2.3×)****8 49K461K tok/s (9.4×)**scaling ~1.3× 封顶恢复到 **~5×@8**8 `nvidia-smi` 抽样 **全 8 卡 9599% util**KI-5 时只 12/8 )。loss 轨迹逐位对住单卡 10.90264.8453 before/after 一致)。
- **正确性全绿无回归**15 算子 grad-check5 结构GEMM cuBLASbatched==looped、overfit 27/27AdamW GPU bit-exact + host torchcheckpoint 逐位DDP loss 对单卡 **5.67e-7** + rank diff 0.0loosened `<1e-6`)、**xserv 闭环**v3 ckpt 重导 safetensors registry md5 逐位一致 + xserv 加载服务贪心 "Once upon a time," 对住)。
- **顺手**DDP `ddp_correctness` cross-rank `==0.0` `<1e-6`本机 PCIe-only NCCL run-to-run rank 非逐位可复现diff1.2e-7 ULP 无害承重闸门是 loss-match 5.67e-7`ddp_throughput_scaling` 扩到 world=8。
- **残留**~5×@8 非完美线性grad all-reduce ~7% + 8 卡 PCIe/launch 余量但弱扩展悬崖已消。v4 若要更高线性度,下一步是 **process-per-GPU**(每 rank 独立 CUDA contexttorchrun 式)。
- **残留**~5×@8 非完美线性grad all-reduce ~7% + 8 PCIe/launch 余量但弱扩展悬崖已消曾以为下一步是 **process-per-GPU** rank 独立 CUDA contexttorchrun )——**T17 实测证伪该方向**见下方process-per-GPUT17)」):残留是**通信/PCIe **不是单 CUDA context launch/cuBLAS 串行
- **commit** T11 提交链`cuda: device caching allocator` / `perf: KI-5 …` 那条带 before/after)。
- **历史诊断保留如下**证伪分桶 all-reduce的过程