Files
xtrain/docs/evolution.md
Gahow Wang db70abe450 docs: T20 — Phase-2 systems-depth capstone (reframe README to two phases)
Re-conclude xtrain as TWO phases now that Phase-2 (T14–T18) is merged on main:

README.md
- Status header: "complete (T1–T13) + scaling v0–v8" → "complete — two phases"
  (Phase 1 = from-scratch stack T1–T13 + v0–v8 scaling study; Phase 2 = the five
  deferred systems-stack features T14–T18).
- Crate table: note the Phase-2 additions (fused flash-attn + repeat_kv + dropout
  in autodiff; GQA + dropout in model; grad-accum in train; process-per-GPU
  launcher in distributed).
- Build-journey section retitled Phase 1 + Phase 2; replaced the run-on T14–T18
  prose with a structured "## Phase 2" summary (5 features + honest results:
  flash = mem-not-walltime win, GQA group-sum backward, grad-accum −74% mem,
  dropout × recompute bit-exact, T17 throughput-neutral falsification).
- Engineering lessons: T17 added as the THIRD profile-first falsification;
  reinforced honest-correctness with the Phase-2 hard gates + md5 b04fc9f9.
- Doc index: doc range …14-* → …17-*; KI status line (process-per-GPU CLOSED,
  KI-4 accepted tradeoff).

docs/evolution.md
- New "三·五、Phase 2 systems-depth synthesis": ties the 5 features into the
  per-axis (算法/架构/Infra/数据) narrative + the two integration notes.

docs/known-issues.md
- KI-4 reframed as a deliberately-accepted modeling tradeoff (保 xserv closed
  loop; T19 DROPPED), not "open".
- New integration notes: (a) DDP tests need --test-threads=1 (parallel deadlock);
  (b) fresh-train md5 is non-deterministic (atomicAdd reduction order) → the valid
  determinism gate is export re-determinism, not fresh-train reproduction.
- (process-per-GPU item was already CLOSED=measured no-op in T17.)

Docs-only; no code touched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 18:11:47 +08:00

89 lines
19 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# xtrain 演进总览 — 按维度记录每次变化
每个里程碑(**T# 基建 phase** 或 **v# 训练 run**)在四个维度上分别改了什么、结果如何。
这是活文档:**每次新 run 收尾时追加一行/一段**。细节见各 `docs/runs/0N-*.md`、各 phase 设计文档、`docs/known-issues.md`
四个维度:**算法**autograd/优化器/精度/反向数学)· **模型架构**dim/层/头/算子)· **Infra**(构建/显存/并行/吞吐)· **数据集**(语料/token/epoch/tokenizer
---
## 一、基建 phaseT1T13 + Phase 2 systems-depth—— 主要动「算法」与「Infra」
| Phase | 维度 | 变化 | 结果 / 验证 |
|---|---|---|---|
| T1 | Infra | Rust↔CUDA FFI 构建链build.rs+nvcc, `no_cuda` cfggitea↔dash5 流 | vector-add 跑通 |
| T2 | Infra | Tensor 抽象dtype/shape/Storage, H↔D 拷贝)+ elementwise kernel | roundtrip 保真 |
| T3 | 算法 | 手写 tiled GEMM fwd/bwd + finite-diff 梯度检查 harness | fwd vs cuBLAS 1e-7bwd vs finite-diff |
| T4 | 算法 | tape autograd 引擎 + 11 算子 backward含梯度扇出累加attention 由 matmul+softmax 组合 | 每算子 finite-diff ≤2e-2 |
| T5 | 模型架构 | 组装 tiny decoderRoPE+RMSNorm+SwiGLU+ embedding/reshape/transpose 算子 | overfit 27/27 + PyTorch 对拍 B>1 |
| T6 | 算法 + 数据集 | 手写 AdamW + 训练 loop + LR sched + grad clip + checkpointgpt2 BPE + TinyStories | 真训出连贯英文 |
| T7 | Infra | cuBLAS matmul + GPU 端 AdamW/grad-norm + 去 per-op sync | **~3×**2.7K→8.5K tok/s零回归 |
| T8 | Infra | NCCL DDP单进程 thread-per-GPU+ 梯度 all-reduce | 多卡(当时弱扩展 ~1.4× |
| T9 | 算法/模型架构 + Infra | **加 per-head QK-norm**Qwen3 兼容safetensors 导出 | xserv 闭环:贪心**逐 token 一致** |
| T10 | 算法/Infra | **batched 多序列 forward**linears flatten `[B·S,dim]` + fused batched SDPA + 每序列 RoPE | **单卡 1524×**MFU 0.4%→14%(修 KI-1 |
| T11 | Infra | **device caching/pool allocator**(复用 op 输出显存,消 per-step cudaMalloc | 单卡 2.3×**8卡 461K tok/s** 近线性(修 KI-5 |
| T12 | 算法/Infra | **bf16 混合精度**fp32 mastercuBLAS GemmExnorm/softmax/CE 保 fp32 | dim768 OOM 解除29% 显存/+13% tok/s修 KI-2 |
| T13 | 算法/Infra | **激活重计算**per-block gradient checkpointing前向 no-tape + 反向重算,`backward_seeded` | 梯度对非重计算版**逐位一致**(0.00)dim768 31.1→14.6GB**dim1024 batch32 OOM→16.6GB 装下**(修 KI-3解锁 v8 |
| T14 | 算法/Infra | **融合 flash-attention kernel**(手写单 kernelonline softmax、tiled over KV、**不物化 N×N scores**flash 式 bwd重算 scores + `D=ΣdO·O` 化简雅可比 + dQ/dK/dVopt-in `--flash`,默认保 composedPhase 2 | fwd 对 composed 6.7e-5、bwd 对 composed dQ 1.7e-5、PyTorch B>1 7.9e-6、flash==composed loss rel 0.0**峰值显存 16%@seq1024 / 23%@seq2048**(不物化 N×N收益随 seq 增长tok/s ~2.32.8×hd=64 小头维干不过 cuBLAS tensor-coreflash 已知权衡=胜场在显存md5 闭环逐位一致 |
| T15 | 模型架构 | **真 GQA**`num_kv_heads<num_heads`wk/wv 投影到 `kv_dim`,新 `repeat_kv` broadcast 算子把 K/V 复制 `group=nh/num_kv` 份喂给**未改动**的 composed/flash 两条 SDPA分组约定对齐 xserv repeat_kv `dst=kvh·group+r``repeat_kv` 反向=组内 group 行**确定性求和**(无 atomic→ 多组 q 头梯度汇一个 kv 头;`num_kv_heads` 进 Config(默认=nh→MHA)、`--kv-heads` flag、导出写真 `num_key_value_heads`Phase 2 | repeat_kv grad-check 2.1e-4(group3)+group1 identity 逐位GQA flash==composed fp32 grad 4.1e-5/bf16 在带;**group1 对 MHA 逐位一致**(回归保护)PyTorch GQA B>1 对拍 composed/flash 各 loss 1.7e-8/logits 2.3e-5/25 grad 进 rtol小 GQA(8h/2kv) 训 600 步 10.9→3.15 连贯;**xserv 闭环真 GQA**(num_kv 2<8)2/3 prompt token-identical1 BF16 漂移处晚分叉MHA 默认 export md5 逐位一致(b04fc9f9) |
| T16 | 算法/Infra | **梯度累积**N micro-step每个 micro-loss `×1/N` backwardtape SUM 累加 一次 AdamW step+zero`--accum-steps`**DDP 只在累积边界 all-reduce**中间 micro-step 不发 NCCL`/world` `1/N` 正交显存随 micro 不随有效 batch | 等效大 batch**逐位贴合**loss rel 8.5e-8grad rel 3.8e-5`accum=1` 逐位回归(0.00)DDP+accum 对单卡 loss 5.7e-7/ rank 一致**显存平**同有效 batch 64big-batch 27.7GBaccum(4×16) **7.2GB(74%)**big-batch OOM accum 装下全回归+xserv 闭环 md5 一致 |
| T18 | 算法 | **dropout**手写 counter-based 设备 RNG Bernoulli mask训练 inverted 1/(1-p) scalingeval 恒等 autodiff `dropout` 算子fwd 生成+施加 maskbwd 用同 mask residual/ffn 两处`--dropout` flag 默认 0 | 固定 seed grad-check E[out]≈input + keep1-p**p=0 与无 dropout 逐位一致**recompute(T13) 组合下梯度仍逐位一致counter-based seed 重算复现同 mask全回归 + xserv 闭环绿导出/推理 dropout |
| T17 | Infra | **process-per-GPU**torchrun `launch_processes` 每卡 spawn 一个 worker 进程=独立 CUDA contextlauncher 一次性铸 `ncclUniqueId` **hex 编码注入子进程 env**——无共享 FS/TCP无竞态worker envbind device`DdpContext::init`+`build_model`+`train_rank` **全复用 T8 零改动** `train_ddp_mp` bin/`ddp_proc` test**保留 thread-per-GPU 旧路径**scope=process-per-GPU onlyZeRO-1 用户 dropPhase 2 | 正确性全绿proc vs 单卡 loss 5.67e-7、**proc vs thread-per-GPU 1.5e-7**、 rank 1.19e-7(<1e-6)、全回归+xserv 闭环 md5 逐位一致 `b04fc9f9`。**⚠️关键发现实测证伪原假设本尺度 process-per-GPU 对吞吐中性**——thread vs proc @ {1,2,4,8} = {1.00/1.61/2.98/**5.27**}× vs {1.00/1.60/2.94/**5.31**}×<1% 噪声内8 卡全 9599% util 残留 ~5.3×@8 非线性是 **NCCL all-reduce + 本机 PCIe 拓扑墙****** CUDA context 串行KI-5/T11 doc 的猜想被钉死推翻方法论同 T11 证伪分桶 all-reduce」)。净价值=落地 torchrun 式标准链路 + 把误导性 backlog 项实测关闭默认训练路径不变 |
---
## 二、Scaling runsv0v8—— 主要动「模型架构」与「数据集」
架构始终是 **Qwen3-style**RoPE + RMSNorm + QK-norm + SwiGLUgpt2 50257 词表逐版放大 dim//v8 起首次拨容量轴到 dim1024其余维度逐版变化如下
| ver | 模型架构dim//·hd · 核心/总参 | 数据集语料 · 实训 token · epoch | 算法/精度 | InfraGPU · 吞吐 | 结果val · 备注 |
|---|---|---|---|---|---|
| v0 | dim32/4L/2h · 41K/3.26M | TinyStories 3MB 切片 · ~0.72M · | fp32 单序列 | 1 GPU | val 3.80toy不可用 |
| v1 | dim256/8L/8h · 8.4M/34M | TinyStories 全量 · 5.1M · 0.01ep | fp32 单序列 | 1 GPU · 3.3K | val 2.58 |
| v2 | dim384/12L/12h · 28M/67M | TinyStories · 37M · 0.08ep | fp32 单序列 | 4 GPU DDP · 3.6K | val 1.71暴露 KI-1/弱扩展 |
| v3 | dim512/16L/16h · 67M/119M | TinyStories · 246M · 0.53ep | fp32 **batched(T10)** | 1 GPU · 26K | val 1.30 |
| v4 | dim768/18L/24h · 127M/205M | TinyStories · 721M · 1.54ep | fp32 batched | **8 GPU(T11)** · 145K | val 1.17仍欠拟合 |
| v5 | dim768/18L** v4** | TinyStories · 2.49B · **5.33ep** | **bf16(T12)** | 8 GPU · 217K | val **1.11**:⚠**TinyStories 饱和**3.5×数据仅5% |
| v6 | dim768/18L v4/v5 | **FineWeb-edu** 真实网页 · 2.29B · 1.02ep | bf16 | 8 GPU · 218K | val **3.07**:⚠**FineWeb 留出集 v0v5 不可比**真实网页熵高~3.0 是预期判据=采样质量+transfer。第一版脱离 TinyStories**语言种类质变**小故事真实说明文transferTinyStories val 2.75(v5 native 1.11)纯通用数据对窄分布有代价val 末步仍单调降=未饱和 |
| v7 | dim768/18L v4/v5/v6 | **同 v6 的 FineWeb-edu 子集**非新数据)· 3.28B · **1.45ep** | bf16 | 8 GPU · 218K | val **3.01** v6 可比):⚠**同子集多 epoch 近天花板**——唯一变量=epoch(1.02→1.45),多喂 ~1B token val 0.05 ~step44000 后走平采样无质变 v5 TinyStories 数据量饱和同类重复老数据边际薄·更多数据要** shards** |
| v8 | **dim1024**/18L/**32h** · **226M/329M**+78% 容量ffn 2730 | **同 v6/v7 的 FineWeb-edu 子集**非新数据)· 2.36B · **1.05ep** | bf16 **+ 激活重计算(T13)** | 8 GPU · 129K重算税 | val **2.98** v6/v7 可比):⭐**容量轴 A/B——容量有用**唯一变量=dim768→dim1024 ~1ep v6 3.07→**2.98**(↓0.085 v8(1.05ep) < v7(1.45ep 更多老数据) 3.01 放大容量 > 重复老数据 ⇒ v6/v7 部分 capacity-limited。⚠但增益仅 ~3%、val 末步**仍在降未饱和** ⇒ **单轴(数据/容量)单步都已 ~3%/lever = 全面边际递减,要双轴一起 scale(Chinchilla)** |
> 实训 token = steps×batch×seq非数据集大小。val 同一 1M-token TinyStories 留出集v0v5 可比v6 起换 FineWeb-edu 留出集,分布不同、与 v0v5 不可比v6/v7/v8 同一 FineWeb 留出集、三版彼此可比 3.07/3.01/2.98)。
---
## 三、各维度的累积演进(轴向看一条线怎么走的)
- **算法**:手写 autograd(tape)+扇出累加 → AdamW/LR-sched/grad-clip → +QK-norm(Qwen3) → batched forward → bf16 混合精度(fp32 master) → 激活重计算(T13) → 融合 flash-attention(T14online softmax + flash 式 bwd) → 梯度累积(T16复用 tape SUM等效大 batch 而显存随 micro) → dropout(T18counter-based 设备 RNG + inverted scalingtrain/eval 切换)。
- **模型架构**:固定 Qwen3-styledim **32→256→384→512→768→1024**v8 首拨容量轴,头数 24→32核心参数 **41K→226M**(总 3.26M→329M。+QK-norm(T9Qwen3 兼容) → **真 GQA(T15`num_kv_heads<num_heads`repeat_kv broadcast + 组内梯度求和;默认=nh→MHA 逐位回归)**——架构补齐到现代 LLM 标配MHA/GQA/MQA 一条 `num_kv_heads` 轴),两条 SDPA(composed/flash) 共用同一 broadcast导出真 `num_key_value_heads` 且 xserv 闭环。
- **Infra**:单卡 fp32 → cuBLAS/GPU-optim(T7) → NCCL DDP(T8) → batched forward(T10) → caching allocator(T11) → bf16(T12) → 激活重计算(T13解锁 dim1024) → flash-attention(T14不物化 N×Nattention 显存收益随 seq 增长) → 梯度累积(T16DDP 只在累积边界通信,显存随 micro 不随有效 batch) → process-per-GPU(T17torchrun 式独立进程/CUDA context复用 T8 train_rank 零改动)。吞吐 **3.3K→217K tok/s**dim768 bf16dim1024+重算 ~129K重算税MFU **0.4%→17%**(每次提升都对应一块 perf 基建,详见 known-issues + MFU 分析。T13/T14/T16 是三条**显存杠杆**重计算压激活峰值、flash 不物化 N×N attention scores、梯度累积解耦有效 batch 与激活显存),可叠加放大有效 batch。**T17 实测=负结果记账**process-per-GPU 在本尺度对吞吐**中性**thread ~5.27× vs proc ~5.31×@8,差<1% 噪声8 卡全 9599% util 残留非线性是 NCCL/PCIe 通信墙、**** context 串行—— KI-5/T11 doc 长挂的process-per-GPU 是残留串行的解猜想实测钉死推翻方法论同 T11 证伪分桶 all-reduce」)。
- **数据集**TinyStories 3MB 切片 全量 TinyStoriesepoch 0.015.33**至饱和**)→ **v6 毕业到 FineWeb-edu 真实网页**2.255B 语料1.02ep)→ **v7 同子集多 epoch1.45ep,近顶)→ v8 同子集换大模型**dim10241.05ep)。tokenizer 全程 gpt2 BPE复用 xserv-tokenizerv6 刻意不换 tokenizer 以隔离数据来源变量KI-4 留后续版本)。
- **v5v6 数据轴的质变**v0v5 都吃合成幼儿故事TinyStories低熵词汇受控v5 证明同尺寸模型在它上面已饱和v6 第一版换成**真实教育类网页文本**FineWeb-edu语言种类发生质变——采样从只会写小故事变成能写历史/科学/说明文」。
- **同子集多 epoch 也有天花板v6→v7**v6 FineWeb val 才训 1.02ep末步仍单调降曾被读作还没喂够」;v7 **同一 2.255B 子集**喂到 1.45ep ~1B tokenFineWeb val 0.053.073.01 ~step44000 后走平采样无质变 **该子集在 dim768 已近天花板**这与 v5 TinyStories 数据量饱和是**同一类现象****「重复喂老数据边际都薄无论是 v5 的同语料多 epoch 还是 v7 的同子集多 epoch**。真正抬天花板的是 v6换更广的新语料那一步——**杠杆在更多样的新 token」,不在同数据多读几遍」**。后续要继续降 val必须补** FineWeb shards**更多样不重复不是同子集加 epoch
- **val 可比性**v0v5 val 是同一 TinyStories 1M 留出集彼此可比**v6 起换 FineWeb-edu 留出集分布不同val 不能和 v0v5~1.1比大小**——真实网页熵高~3.0 是预期而非回退**v6/v7/v8 同一 FineWeb 留出集三版彼此可比**3.073.012.98)。v6 的判据还有采样质量 + **transfer eval**v6TinyStories val 2.75 vs v5 native 1.11量化纯通用数据对窄分布的代价」)。
- **容量轴有用,但也只有 ~3%v8**v6/v7 dim768 吃不动更多数据」,v8 用最干净的 A/B 回答了是数据见够还是容量不够」——**冻结数据子集纯把 dim768dim1024core 127M226M+78%** ~1 epoch FineWeb val **3.07→2.98↓0.085** v81.05ep还低于 v71.45ep 更多老数据 3.01。⇒ **容量有用v6/v7 部分是 capacity-limited不全是数据见够**放大容量比给小模型多喂老数据更值。**但增益只有 ~3%**与数据轴单步杠杆同量级
- 🧭 **元结论:单轴单步都已 ~3%/lever = 全面边际递减,要双轴一起 scaleChinchilla 小尺度复现)**把三条轴并起来看——数据量轴v5/v7 同子集多 epoch饱和~1.65%/)、数据广度轴v6 换语料是一次性换分布红利)、容量轴v8有用但 ~3%)——** v8任何单轴的单步杠杆都收敛到 ~3%/lever**。 v8 容量 +78% 却只配同样的 2.36B tokenval 末步仍在降 数据立刻成新瓶颈。⇒ **要继续进步,容量与数据必须匹配地一起 scale而不是单独猛拨一根轴**——这正是 Chinchilla 在这个 toy 尺度上的复现
## 三·五、Phase 2 系统栈深度综合T14T18 五条特性按四维收束)
scaling 科学线v0v8收官后项目重启回到本职学训练全栈」,把此前**显式延后**的五条训练栈特性补齐区别于 Phase 1 修真实瓶颈」(T10T13 每条都治一个 KIPhase 2 **补齐标配 + 一次诚实的负结果**。五条按四维落点
- **算法**三条 = **flash-attention(T14)** + **梯度累积(T16)** + **dropout(T18)**
- 三条里 **T14/T16 与 Phase 1 的 T13 一起构成可叠加的「显存三杠杆」**T13 压激活峰值T14 不物化 N×N attention scores收益随 seq 增长)、T16 解耦有效 batch 与激活显存显存随 micro 不随 N×)——三者正交叠加可放大有效 batch / seq
- **T18 dropout 的设计点是 stateless counter-based RNG**mask `(seed, 元素下标)` 无状态产出所以** T13 激活重计算天然 bit-exact 组合**——反向重算时同 seed 重生同一张 mask梯度逐位一致这是两条 Phase-2/Phase-1 特性的正交性被正确性闸门钉死的一个例子
- 诚实账flash-attention **赢在显存不赢墙钟**hd=64 小头维手写 kernel ~2.3× 慢于 cuBLAS tensor-coreopt-in 默认关不回归
- **模型架构**一条 = **真 GQA(T15)**:架构补齐到现代 LLM 标配MHA/GQA/MQA 一条 `num_kv_heads` )。实现关键 = `repeat_kv` broadcast 算子的**反向组内确定性求和 atomic** K/V 零改动喂进 composed + flash 两条 SDPA`group=1` MHA **逐位一致**作回归保护导出真 `num_key_value_heads` xserv 闭环真 GQA
- **Infra**一条 = **process-per-GPU(T17)**,但它是**实测负结果**而非性能提升:落地 torchrun 式独立进程/CUDA context 标准链路复用 T8 train_rank 零改动却实测本尺度**吞吐中性**thread ~5.27× vs proc ~5.31×@8<1%8 卡全 9599% util KI-5/T11 doc 长挂的共享单 context 致残留 ~5×@8猜想**钉死推翻**——残留是 NCCL all-reduce + PCIe 拓扑墙 context 串行。**方法论与 Phase 1 T11证伪分桶 all-reduce」)一脉相承profile/measure-first。**
- **数据集**零条Phase 2 不动数据轴KI-4 小词表用户拍板 **drop 以保 xserv gpt2-tokenizer 闭环**转记为接受的建模权衡 known-issues)。
**Phase 2 的统一闸门 = 诚实正确性,全程未为凑绿放宽容差**flash==composedgrad/PyTorch、GQA group=1 == MHA 逐位accum=1 逐位dropout p=0 逐位 + dropout×重算 bit-exact每条特性默认路径不变、**xserv 闭环 md5 `b04fc9f9` 两阶段全程逐位一致**。
> 📌 两条 integration 发现非回归pre-existing记账① **DDP 三个测试并行会争 2 卡 deadlock** → 文档/测试用 `--test-threads=1`(或标 serial跑。② **fresh-train md5 run-to-run 不定**——反向 atomicAdd 归约序非确定 → 有效的确定性闸门是**导出export重确定性**(同 ckpt 重导 safetensors md5 逐位一致),**不是** fresh-train 复现。
## 四、perf 杠杆台账(详见 [known-issues.md](known-issues.md)
- **已修**KI-1 单序列 launch-boundT10)· KI-5 per-op cudaMalloc 串行T11)· KI-2 bf16/OOMT12)· KI-3 激活重计算T13解锁 dim1024v8 用上)。
- **实测关闭负结果**process-per-GPUT17)——曾挂在 KI-5/T11 doc 作残留非线性的拟修复方向T17 实测**吞吐中性**thread ~5.27× vs proc ~5.31×@88 卡全满载残留是 NCCL/PCIe 通信墙非 context 串行 不再是 perf 待办链路本身已落地留作可选路径
- **待办**KI-4 大词表小 vocab接受的建模权衡)· 要更高多卡线性 all-reduce overlap / NVLink 互联非本尺度优先)。
- **三次 profile/measure 再动手证伪了错误的拟修复**KI-1加大batch」、KI-5分桶all-reduce」、T17process-per-GPU 解残留串行」),避免了无效大改——profile/measure-first