Files
xtrain/docs/evolution.md
Gahow Wang b39e6e7110 docs: M2a — KV-cache decode engine results (token-identical + length-dependent speedup)
Implementation log (docs/18) + Phase-3 row (evolution.md): the two decode
primitives and their gates, the engine design (host-cache baseline), the
token-identical centerpiece gate, and the measured throughput baseline showing
the cache win is sequence-length-dependent (~1.0x@32, ~1.9x@128, naive OOM@256).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 12:01:10 +08:00

25 KiB
Raw Blame History

xtrain 演进总览 — 按维度记录每次变化

每个里程碑(T# 基建 phasev# 训练 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-normQwen3 兼容safetensors 导出 xserv 闭环:贪心逐 token 一致
T10 算法/Infra batched 多序列 forwardlinears 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.6GBdim1024 batch32 OOM→16.6GB 装下(修 KI-3解锁 v8
T14 算法/Infra 融合 flash-attention kernel(手写单 kernelonline softmax、tiled over KV、不物化 N×N scoresflash 式 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 模型架构 真 GQAnum_kv_heads<num_headswk/wv 投影到 kv_dim,新 repeat_kv broadcast 算子把 K/V 复制 group=nh/num_kv 份喂给未改动的 composed/flash 两条 SDPA分组约定对齐 xserv repeat_kv dst=kvh·group+rrepeat_kv 反向=组内 group 行确定性求和(无 atomic→ 多组 q 头梯度汇一个 kv 头;num_kv_heads 进 Config(默认=nh→MHA)、--kv-heads flag、导出写真 num_key_value_headsPhase 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-identical、1 在 BF16 漂移处晚分叉MHA 默认 export md5 逐位一致(b04fc9f9)
T16 算法/Infra 梯度累积N 个 micro-step每个 micro-loss ×1/N 再 backwardtape SUM 累加 → 一次 AdamW step+zero--accum-stepsDDP 只在累积边界 all-reduce(中间 micro-step 不发 NCCL/world1/N 正交);显存随 micro 不随有效 batch 等效大 batch逐位贴合loss rel 8.5e-8、grad rel 3.8e-5accum=1 逐位回归(0.00)DDP+accum 对单卡 loss 5.7e-7/跨 rank 一致;显存平:同有效 batch 64big-batch 27.7GB→accum(4×16) 7.2GB(74%)big-batch OOM 而 accum 装下);全回归+xserv 闭环 md5 一致
T18 算法 dropout(手写 counter-based 设备 RNG → Bernoulli mask训练 inverted 1/(1-p) scaling、eval 恒等);新 autodiff dropout 算子fwd 生成+施加 maskbwd 用同 mask接 residual/ffn 两处;--dropout flag 默认 0 固定 seed grad-check 过E[out]≈input + keep≈1-pp=0 与无 dropout 逐位一致recompute(T13) 组合下梯度仍逐位一致counter-based seed 重算复现同 mask全回归 + xserv 闭环绿(导出/推理 dropout 关)
T17 Infra process-per-GPUtorchrun 式:launch_processes 每卡 spawn 一个 worker 进程=独立 CUDA contextlauncher 一次性铸 ncclUniqueIdhex 编码注入子进程 env——无共享 FS/TCP、无竞态worker 读 env→bind 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 项实测关闭;默认训练路径不变
T21 Infra DDP-dropout wiring fixV9-PILOT 暴露T18 只把 dropout 接进单卡 train.rstrain_ddp bin 无 --dropout flag、train_rank 从不调 model.train() → DDP 下 dropout 被静默忽略。补:--dropout flag + train_rank 每步 model.train(),镜像单卡 train/eval 纪律——eval_loss 翻 eval 后由每步 train() restore加 DDP-dropout 回归测试堵缺口 DDP-dropout 回归测试绿p>0 下 dropout liveloss 轨迹对 p=0 有可观差异pre-T21 会逐位相同、p=0 对无 dropout 路径逐位一致、run 后 is_training()==true;既有 DDP loss-match/跨 rank 测试不变。元教训op/单卡单元测试漏掉 launcher 级 integration gap只有真实启动器端到端跑pilot才暴露

二、Scaling runsv0v10—— 主要动「模型架构」与「数据集」

架构始终是 Qwen3-styleRoPE + RMSNorm + QK-norm + SwiGLUgpt2 50257 词表),逐版放大 dim/层/头v8 起首次拨容量轴到 dim1024v9 进入 dim1280+真 GQA 双轴点v10 固定架构只补数据轴);其余维度逐版变化如下:

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语言种类质变小故事→真实说明文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
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)
v9 dim1280/18L/40h/10kv GQA · 357M/486Mffn 4096 FineWeb-edu 扩展 shards 000-009 · 6.01B · ~1.00ep bf16 + recompute + flash + grad-accum + true GQA 8 GPU · 78.6K21.25h val 2.8854(与 v6-v8 可比):双轴 Chinchilla 点有效——容量从 v8 226M→357M同时数据从 2.255B 子集→6.013B tokenbest val 比 v8 再降 0.0947 (~3.2%)。采样写真实说明文更稳一些,但 greedy 重复仍明显;收益仍是稳健增量而非质变
v10 同 v9 FineWeb-edu 扩展 shards 000-010 · 6.765B · ~1.00ep bf16 + recompute + flash + grad-accum + true GQA 8 GPU · 79.0K23.86h moving-tail val 2.8816;固定 eval v1 上 v9 2.9278→v10 2.8814。结论:补 shard010 对新分布有效,但只补数据轴不解决 greedy 重复;后续应固定 eval set并优先试更大模型+长 context

实训 token = steps×batch×seq非数据集大小。v0v5 的 val 是同一 1M-token TinyStories 留出集。v6 起换 FineWeb-edu 且 v9/v10 追加新 shards 会移动默认 tail-heldout严格横比改用 fixed eval v1shard010 tail 1M v6/v7/v8/v9/v10 = 3.2328 / 3.1850 / 3.1515 / 2.9278 / 2.8814


三、各维度的累积演进(轴向看一条线怎么走的)

  • 算法:手写 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→1280v8 首拨容量轴v9 进入 dim1280核心参数 41K→357M(总 3.26M→486M。+QK-norm(T9Qwen3 兼容) → 真 GQA(T15num_kv_heads<num_headsrepeat_kv broadcast + 组内梯度求和;默认=nh→MHA 逐位回归v9 用 40 query / 10 kv——架构补齐到现代 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/sdim768 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.01→5.33至饱和)→ v6 毕业到 FineWeb-edu 真实网页2.255B 语料1.02ep)→ v7 同子集多 epoch1.45ep,近顶)→ v8 同子集换大模型dim10241.05ep)→ v9 扩新 FineWeb shards 到 6.013B token 并同步放大模型v10 补 shard010 到 6.765B token只拨数据轴。tokenizer 全程 gpt2 BPE复用 xserv-tokenizer保闭环优先KI-4 接受)。
    • v5→v6 数据轴的质变v0v5 都吃合成幼儿故事TinyStories低熵、词汇受控v5 证明同尺寸模型在它上面已饱和v6 第一版换成真实教育类网页文本FineWeb-edu语言种类发生质变——采样从「只会写小故事」变成「能写历史/科学/说明文」。
    • ⚠️ 同子集多 epoch 也有天花板v6→v7v6 的 FineWeb val 才训 1.02ep、末步仍单调降曾被读作「还没喂够」v7 把同一 2.255B 子集喂到 1.45ep(多 ~1B tokenFineWeb val 仅 ↓0.053.07→3.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 是预期而非回退。v9/v10 追加 shards 后默认 tail-heldout 会移动,不能再只看 moving-tail best。为后续建立 fixed eval v1shard010 tail 1Mv6/v7/v8/v9/v10 = 3.2328 / 3.1850 / 3.1515 / 2.9278 / 2.8814
    • 容量轴有用,但也只有 ~3%v8v6/v7 在 dim768 上「吃不动更多数据」v8 用最干净的 A/B 回答了「是数据见够还是容量不够」——冻结数据子集、纯把 dim768→dim1024core 127M→226M+78%,同 ~1 epoch 下 FineWeb val 3.07→2.98↓0.085,且 v81.05ep)还低于 v71.45ep 更多老数据)的 3.01。⇒ 容量有用v6/v7 部分是 capacity-limited不全是数据见够;放大容量比「给小模型多喂老数据」更值。但增益只有 ~3%,与数据轴单步杠杆同量级。
    • 双轴一起 scale 有效v9v9 把 v8 的提案落地:模型 core 226M→357M数据 2.255B 子集→6.013B token实训 6.012Bbest FineWeb val 2.9801→2.8854,再降 0.0947 (~3.2%)。这确认 Chinchilla 式双轴方向正确;但收益仍是 ~3% 级稳健增量greedy 重复仍在,说明小尺度下“更好 val”尚未完全转化成肉眼质变。
    • 📌 只补数据轴边际有限v10v10 保持 v9 架构,仅补 shard010 到 6.765B token。fixed eval v1 上 v9 2.9278→v10 2.8814,说明新 shard 分布被学到;但 moving-tail best 只从 2.8854→2.8816,且 greedy 复读不变。下一步更值得改模型/context而不是继续一片片补数据。

三·五、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 RNGmask 由 (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 两条 SDPAgroup=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 复现。

三·六、Phase 3 后训练栈SFT → KV-cache → DPO → GRPO详见 18-post-training-rl-sft.md

Phase 1/2 把预训练全栈学完后Phase 3 转向后训练 infra(对齐方向)。锁定路线 DPO→GRPOreward model 可选)、rule-based 可验证 reward 优先KV-cache 增量解码引擎前置自建、任务取可验证算术(确定性 exact-match给 RL 干净可证伪信号)。里程碑 M1SFT baseline→ M2KV-cache 解码引擎token-identical 闸门)→ M3DPO→ M4GRPO→ M5可选 RM。按维度落点

  • 算法后训练损失族——SFTassistant-only masking已有→ DPOseq_logprob 算子 + Bradley-Terry/σ(Δ) 偏好损失frozen reference→ GRPOgroup-relative advantage无 critic + clipped PG + KL leash。每条沿用 Phase 1/2 闸门规矩:新损失/算子有限差分 grad-check + PyTorch parity + 退化检查β→0 / G=1 / ε→∞ / ref==policy+ 一条可证伪「真在学」信号reward margin↑ / 合成 RL overfit
  • Infra**KV-cache 增量解码引擎M2前置**是这一阶段的硬核——per-layer K/V cache + 单 token 增量 forwardprompt 灌一次 cache 后逐 token 解码)+ ragged 批量解码。硬闸门 = 解码逐 token 等价于全重算 greedy(同 xserv 导出闭环的逐位纪律),并先记解码吞吐 baselineprofile-first。它是 DPO 造对 + GRPO rollout 的共享底座。
  • 数据集:可验证任务自带数据生成器——两操作数整数算术(+ ×rule-based checker 读 \boxed{} 做 exact-match是 M1 SFT 数据 + M3 造对 + M4 GRPO reward 的单一共享 spec。
  • 模型架构:复用 v12 1.05B 基座,不动架构。

M1SFT task baseline已落地:可验证算术任务 + 数据生成器 + 评分器一套host-side 9/9 单测过masking、SFT-target 自洽 2000 样、parser 边界、种子确定性。dash5 单卡从 v12 基座 SFTloss 4.68→~0.34best val 0.386)。100 留出题 eval格式 \boxed{} 习得率 base 0% → SFT 100%;算术正确率 8%。——SFT 只买格式0%→100% 干净落地),算术正确性是 base 模型本身弱项(如 46*80 框成 3380正是 M3/M4 的可验证 reward 要去补的残差。一条诚实账M1 用的是朴素无 KV-cache 采样器(每 token 全量 forward100 题已经很慢——这正是 M2 解码引擎前置的动机。

M2aKV-cache 增量解码引擎,单序列,已落地):两个 forward-only 原语 + 裸 Tensor 逐 token block forward各自隔离闸门。rope_at(绝对位置 RoPE新 kernel不动训练 rope → 训练路径零风险)逐位等于全序列 rope 的对应行;decode_attention(单 query × cached-K/V由现成 strided-gemm + 普通 softmax 组合,零新 kernel)等于全 causal attention 末行max|Δ| 6e-8。引擎 generate_greedy_cached 镜像 block_forward 在 Tensor 层(无 autograd tape推理不需梯度公开 params() 稳定顺序拿权重(零 model 可见性改动)。核心闸门 = token-identical:与朴素全重算贪心逐 token 一致(小 GQA 单测 + v12 1.05B 上 cached eval 与 naive 逐字节相同format 100/100, correct 8/100吞吐 baselinev12, batch1, F32profile-first 实测)= cache 收益随序列长度而定max_new 32 ≈ 持平108 vs 111短序列 launch 开销 bound、128 ~1.9×69 vs 133、256 naive OOM vs cached 129 tok/s。cached 吞吐近恒定O(1)/token + 恒定显存naive 衰减O(t)/tokenO(seq²) 图 → OOM。⇒ 短 eval prompt overhead-bound、cache 几乎无收益,真正受益的是长 rolloutDPO 造对 / GRPO completion——与 T17process-per-GPU 吞吐中性)同一条 measure-first 教训:收益真实,但只在真正压到瓶颈的 regime 里。M2a 的 per-layer 主机往返是短序列 overhead-bound 的一部分原因M2bdevice 端 cache + 批量 ragged针对它。

四、perf 杠杆台账(详见 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」、T17「process-per-GPU 解残留串行」避免了无效大改——profile/measure-first。