v7 = same arch as v4/v5/v6 (dim768/18L, bf16, 8-GPU DDP global 256), trained the SAME 2.255B-token FineWeb-edu subset to 1.45 epoch (vs v6's 1.02), best FineWeb val 3.0149 (v6 3.0652). Exported + archived to registry v7-fineweb-edu-dim768, serves in xserv (coherent expository English, ~v6 quality). Key finding: more epochs of the SAME subset gave only ~0.05 val drop and the curve flattened (~step 44000) with no sampling quality gain → the 2.255B FineWeb subset is near its ceiling at dim768. Same class as v5's TinyStories data-volume saturation: repeating old data has thin margins; true further gains need FRESH shards (more diverse tokens), as v6's corpus-swap (which raised the ceiling) showed. Adds docs/runs/07-v7-*.md; updates docs/runs/README.md (+v7 row, intro saturation note, v8 proposal) and docs/evolution.md (+v7 row, dataset-axis ceiling note). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
7.7 KiB
7.7 KiB
xtrain 演进总览 — 按维度记录每次变化
每个里程碑(T# 基建 phase 或 v# 训练 run)在四个维度上分别改了什么、结果如何。
这是活文档:每次新 run 收尾时追加一行/一段。细节见各 docs/runs/0N-*.md、各 phase 设计文档、docs/known-issues.md。
四个维度:算法(autograd/优化器/精度/反向数学)· 模型架构(dim/层/头/算子)· Infra(构建/显存/并行/吞吐)· 数据集(语料/token/epoch/tokenizer)。
一、基建 phase(T1–T12)—— 主要动「算法」与「Infra」
| Phase | 维度 | 变化 | 结果 / 验证 |
|---|---|---|---|
| T1 | Infra | Rust↔CUDA FFI 构建链(build.rs+nvcc, no_cuda cfg),gitea↔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-7;bwd vs finite-diff |
| T4 | 算法 | tape autograd 引擎 + 11 算子 backward(含梯度扇出累加);attention 由 matmul+softmax 组合 | 每算子 finite-diff ≤2e-2 |
| T5 | 模型架构 | 组装 tiny decoder(RoPE+RMSNorm+SwiGLU)+ embedding/reshape/transpose 算子 | overfit 27/27 + PyTorch 对拍 B>1 |
| T6 | 算法 + 数据集 | 手写 AdamW + 训练 loop + LR sched + grad clip + checkpoint;gpt2 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) |
单卡 15–24×;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 master,cuBLAS GemmEx,norm/softmax/CE 保 fp32) | dim768 OOM 解除,−29% 显存/+13% tok/s(修 KI-2) |
二、Scaling runs(v0–v7)—— 主要动「模型架构」与「数据集」
架构始终是 Qwen3-style(RoPE + RMSNorm + QK-norm + SwiGLU,gpt2 50257 词表),只放大 dim/层;其余维度逐版变化如下:
| ver | 模型架构(dim/层/头·hd · 核心/总参) | 数据集(语料 · 实训 token · epoch) | 算法/精度 | Infra(GPU · 吞吐) | 结果(val · 备注) |
|---|---|---|---|---|---|
| v0 | dim32/4L/2h · 41K/3.26M | TinyStories 3MB 切片 · ~0.72M · — | fp32 单序列 | 1 GPU | val 3.80(toy,不可用) |
| 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 留出集,与 v0–v5 不可比(真实网页熵高,~3.0 是预期);判据=采样质量+transfer。第一版脱离 TinyStories,语言种类质变(小故事→真实说明文);transfer→TinyStories 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 |
实训 token = steps×batch×seq(非数据集大小)。val 同一 1M-token TinyStories 留出集(v0–v5 可比;v6 起换 FineWeb-edu 留出集,分布不同、与 v0–v5 不可比;v6 与 v7 同一 FineWeb 留出集、彼此可比)。
三、各维度的累积演进(轴向看一条线怎么走的)
- 算法:手写 autograd(tape)+扇出累加 → AdamW/LR-sched/grad-clip → +QK-norm(Qwen3) → batched forward → bf16 混合精度(fp32 master)。
- 模型架构:固定 Qwen3-style;dim 32→256→384→512→768;核心参数 41K→127M(总 3.26M→205M)。
- Infra:单卡 fp32 → cuBLAS/GPU-optim(T7) → NCCL DDP(T8) → batched forward(T10) → caching allocator(T11) → bf16(T12)。吞吐 3.3K→217K tok/s,MFU 0.4%→17%(每次提升都对应一块 perf 基建,详见 known-issues + MFU 分析)。
- 数据集:TinyStories 3MB 切片 → 全量 TinyStories(epoch 0.01→5.33,至饱和)→ v6 毕业到 FineWeb-edu 真实网页(2.255B 语料,1.02ep)→ v7 同子集多 epoch(1.45ep,近顶)。tokenizer 全程 gpt2 BPE(复用 xserv-tokenizer;v6 刻意不换 tokenizer 以隔离「数据来源」变量,KI-4 留后续版本)。
- v5→v6 数据轴的质变:v0–v5 都吃合成幼儿故事(TinyStories,低熵、词汇受控),v5 证明同尺寸模型在它上面已饱和;v6 第一版换成真实教育类网页文本(FineWeb-edu),语言种类发生质变——采样从「只会写小故事」变成「能写历史/科学/说明文」。
- ⚠️ 同子集多 epoch 也有天花板(v6→v7):v6 的 FineWeb val 才训 1.02ep、末步仍单调降,曾被读作「还没喂够」;v7 把同一 2.255B 子集喂到 1.45ep(多 ~1B token),FineWeb val 仅 ↓0.05(3.07→3.01)且 ~step44000 后走平、采样无质变 ⇒ 该子集在 dim768 已近天花板。这与 v5 的 TinyStories 数据量饱和是同一类现象:「重复喂老数据」边际都薄,无论是 v5 的同语料多 epoch 还是 v7 的同子集多 epoch。真正抬天花板的是 v6「换更广的新语料」那一步——杠杆在「更多样的新 token」,不在「同数据多读几遍」。后续要继续降 val,必须补新 FineWeb shards(更多样、不重复),不是同子集加 epoch。
- ⚠️ val 可比性:v0–v5 的 val 是同一 TinyStories 1M 留出集(彼此可比);v6 起换 FineWeb-edu 留出集,分布不同、val 不能和 v0–v5(~1.1)比大小——真实网页熵高,~3.0 是预期而非回退;v6 与 v7 同一 FineWeb 留出集、彼此可比(3.07→3.01)。v6 的判据还有采样质量 + transfer eval(v6→TinyStories val 2.75 vs v5 native 1.11,量化「纯通用数据对窄分布的代价」)。
四、perf 杠杆台账(详见 known-issues.md)
- 已修:KI-1 单序列 launch-bound(T10)· KI-5 per-op cudaMalloc 串行(T11)· KI-2 bf16/OOM(T12)。
- 待办:KI-3 激活重计算(放大到 dim1024+ 时)· KI-4 大词表小 vocab · process-per-GPU(要更高多卡线性时)。
- 两次「先 profile 再动手」证伪了错误的拟修复(KI-1「加大batch」、KI-5「分桶all-reduce」),避免了无效大改——profile-first。