Files
xserv/docs/MOE_PROGRESS.md

11 KiB
Raw Blame History

MoE (gpt-oss-20b) — 工作进度与续作指南

中断原因:用户要重启 dash5 机器IP 等可能变),让我先把当前 MoE 支持工作的状态 完整记录到本文件,重启后据此继续。本文件是"重启后从这里接着干"的唯一入口。

最后更新Phase 18 (PP) 已完成并 pushPhase 19 (MoE/gpt-oss-20b) 刚起步(下载受阻, 架构与参考数学已侦查清楚)。


最新状态2026-05-29 晚)

里程碑xserv 的 gpt-oss MoE 前向已数值验证正确。

  • 模型已下载hf-mirror绕过被墙代理+ MXFP4→BF16 反量化(tools/gptoss_dequant.py 产物 /opt/wjh/models/gpt-oss-20b-bf1635.6GB 单 safetensors+ 拷到 dash5。
  • llama.cpp 金标准就位dash5 的 llama.cpp 原生支持 gpt-ossLLM_ARCH_OPENAI_MOE 用官方 MXFP4 GGUF 验证「17×24=408」正确。无需升级 submodule。
  • gptoss.rs 前向正确:输入 "The capital of France is" → top-1 = token 12366 = " Paris" logit 19.75。打通了全部新组件top-4 routersoftmax-after-topk、interleaved clamped (up+1)*glu experts、attention sinks、sliding window、MXFP4 权重、YaRN RoPE (关键 buggpt-oss 是 yarn rope_typeplain RoPE 会让注意力乱掉→输出回声 prompt、 head_dim 64、q/k/v/o bias。
  • 已 commit + push分支 phase18-pipeline-parallelism)。

还没做(要跑通 AIME/GSM8K 必须补,工作量大):

  1. GPU attention with sinks + 滑窗 kernel(现在是 host CPU 三重循环O(seq²),太慢)。
  2. KV cache 增量解码(现在每生成 1 token 重算整段 prefillO(n²),不可行)。
  3. MoE 提速(现在逐 token、逐 expert host 路由 + 每 expert 50MB H2D 上传)。
  4. 显存BF16 全模型 36GB 单卡放不下 → experts 现在常驻 CPU 按需上传(能单卡跑但慢), 或接 Phase 18 的 PP需把 gptoss 接进 pp_engine

现状能正确跑「几个 token 的前向」,但要跑 30 题 × 上千 token 的 AIME/GSM8K 必须先做 13KV cache + GPU sink-attention + MoE 提速)。这是实打实的下几个阶段。

0. 一句话现状

  • Phase 18 流水线并行 (PP) 全部完成、验证、benchmark已 commit 并 push 到 origin/phase18-pipeline-parallelismgitea
  • 🚧 Phase 19 MoE (gpt-oss-20b) 刚开始:架构 + HF 参考数学已核对(见 docs/19-moe-gpt-oss.md模型还没下载完HF 被墙,正在解决下载路径),代码未动。

1. 环境关键事实(重启后很可能变 / 需重新确认)

  • 本机(开发机,非 GPU/home/gahow/projects/xserv,有公网(走代理)。
  • dash5GPU 机8×RTX 5090无 NVLink0-3/4-7 分组):通过 ssh dash5 访问。
    • 远端仓库目录:/opt/wjh/projects/xserv,模型目录:/opt/wjh/models/
    • dash5 无外网、无 rsync;同步用 ./tools/sync-and-build.shtar over ssh
    • cargo 在 $HOME/.cargo/binCUDA 12.9 在 /usr/local/cuda-12.9
    • ⚠️ 重启后 ssh dash5 的 IP/可达性可能变 —— 先 ssh dash5 hostname 确认; 若连不上,检查 ~/.ssh/configdash* 配置 / 让用户给新地址。
  • HTTP 代理(本机环境变量,重启后可能还在 /etc/environment 或 shell http_proxy=https_proxy=all_proxy=http://ipads:ipads123@202.120.40.82:11235
  • huggingface.co 被墙SSL_ERROR_SYSCALL即使过代理。pypi 可过代理。
  • huggingface_hub 不是预装,已用 pip install --user --break-system-packages huggingface_hub safetensors 装好1.17.0venv 不可用(无 ensurepip

2. gpt-oss-20b 下载(当前卡点

目标:下到本机 ~/models/gpt-oss-20b,再 tar-over-ssh 拷到 dash5 /opt/wjh/models/gpt-oss-20b

已验证可行的下载路径(重启后照此做):

  • huggingface.co 直连/经代理都失败。
  • hf-mirror.com 的 /resolve/308 跳回 huggingface.co(也被墙)——所以不能用 curl -L 跟跳转,huggingface_hubHF_ENDPOINT 在新版(1.17)上 HEAD 也失败。
  • 能用的办法:直接走 hf-mirror 的 /raw/(小文件)和实际 CDN经代理 curl。 已成功取到 config.json200, 1799 bytes
    curl -s -x "http://ipads:ipads123@202.120.40.82:11235" \
      "https://hf-mirror.com/openai/gpt-oss-20b/raw/main/config.json" -o config.json
    
    大文件safetensors要用 /resolve/main/<file>指定 -x 代理、不要 -L 若仍 308 跳回 hf.co则改用 hf-mirror 的 LFS 直链或 huggingface_hub 配合 HF_ENDPOINT=https://hf-mirror.com + 代理(库内部不跟 308下载脚本草稿在 /tmp/dl_shards.sh(重启后 /tmp 会清空,需重建)。

待下载文件3 个分片 + 元数据,总 ~13.5GB MXFP4

  • model-00000-of-00002.safetensorsmodel-00001-of-00002.safetensorsmodel-00002-of-00002.safetensors(注意是 0/1/2 三个,命名 of-00002
  • model.safetensors.index.jsonconfig.jsontokenizer.jsontokenizer_config.jsonspecial_tokens_map.jsongeneration_config.jsonchat_template.jinja

重启后第一步ls -la ~/models/gpt-oss-20b/ 看已下了哪些、wc -c 校验分片大小, 断点续传用 curl -C -


3. gpt-oss-20b 架构config.json 已核对)

字段
layers 24hidden 2880head_dim 64(≠ hidden/heads
heads 64 q-heads / 8 kv-headsGQAn_rep=8
experts num_local_experts 32num_experts_per_tok 4top-4
expert intermediate 2880
vocab 201088max_pos 131072tie_embeddings false
rope_theta 150000核对是否有 rope_scaling/YaRN
sliding_window 128交替层,见 config layer_types
rms_norm_eps 1e-5swiglu_limit 7.0alpha 1.702
量化 MXFP4,仅 expert MLPgate_up/down 的 _blocks+_scalesattn/router/embed/lm_head 为 BF16

4. HF 参考数学(已从 transformers modeling_gpt_oss.py 逐字核对,务必照抄)

完整版见 docs/19-moe-gpt-oss.md §2。要点

Routersoftmax 在 topk 之后

logits = x @ W_router^T + b_router          # [T,32]
top_val, idx = topk(logits, 4)
top_val = softmax(top_val)                  # 只对选中的 4 个归一化
scores = scatter to [T,32] (其余 0)

Expertsfused gate_up交错 ::2 / 1::2clamped(up+1)·glu

alpha=1.702, limit=7.0
gate_up = x @ gate_up_proj[e] + bias        # [.., 2*2880]
gate = gate_up[..., ::2]; up = gate_up[..., 1::2]
gate = clamp(gate, max=limit)               # 仅上界
up   = clamp(up, min=-limit, max=limit)
glu  = gate * sigmoid(gate * alpha)
h    = (up + 1) * glu                        # 注意 (up+1)
y_e  = h @ down_proj[e] + bias
out  = Σ_{e∈top4} scores[t,e] * y_e

Attention带 sinks

scaling = 64 ** -0.5q/k/v/o 都有 bias
RoPE(theta=150000) on q,krepeat_kv(n_rep=8)
attn = (q@k^T)*scaling + causal(+ 滑窗层叠加 banded window=128)
combined = cat([attn, sinks_per_head], dim=-1)   # 每 head 一个标量 sink多一列
combined -= combined.max(-1, keepdim)            # 数值稳定
probs = softmax(combined, -1)
scores = probs[..., :-1]                          # 丢掉 sink 列(概率不归一到 1
o = scores @ v -> merge heads -> @Wo + bo

RMSNorm标准fp32 算 varianceeps=1e-5

参考源码已存(重启后 /tmp 清空需重取):pip download transformers --no-deps 解 wheel 取 transformers/models/gpt_oss/modeling_gpt_oss.py967 行)。


5. MXFP4 反量化expert 权重)

  • expert 张量名:model.layers.{i}.mlp.experts.gate_up_proj_blocks + ..._scales ...down_proj_blocks + ..._scalesbias 是 BF16 的 gate_up_proj_bias/down_proj_bias)。
  • MXFP432 元素一 block共享一个 E8M08-bit 指数scale每元素 4-bit FP4(E2M116 码字)。反量化 val = fp4_lut[code] * 2^(e8m0 - 127)
  • 决策(已定):加载时在 CPU 反量化成 BF16dash5 ~1TB 内存),整模型 ~40GB BF16 单卡放不下 → 走 Phase 18 的 PPPP=2 ~20GB/卡PP=4 ~10GB/卡)。不写 GPU 原生 MXFP4 kernel风险高、慢先正确跑通+对比,后续再优化。

6. 实施路线Phase 19逐步可验证

  1. P19.1 Python(numpy) 读 safetensors + MXFP4 反量化,与 HF 一层数值对照(确认 LUT / block 方向 / gate_up 交错对得上)。不依赖 GPU重启后可先做。
  2. P19.2 crates/xserv-model/src/config.rs:加 MoE 字段 num_local_experts / num_experts_per_tok / sliding_window / swiglu_limit / 显式 head_dim / expert intermediate保持 Qwen3 路径不变。
  3. P19.3 新文件 crates/xserv-model/src/gptoss.rsdenseattn+sinks+bias+滑窗 / RMSNorm / lm_head+ MoE FFN正确优先逐 token top-4 gather→clamped SwiGLU→加权和。 MXFP4 在 from_weights 反量化为 BF16。验收prefill logits 与 HF BF16 容差内一致。
  4. P19.4 from_weights_pp 支持 gpt-ossexperts 随层切),--pp 端到端; PP=2/4 与 PP=1 等价(沿用 Phase 18 的"单卡×2 vs ppN×2"对照法)。注:~40GB 需 PP≥2。
  5. P19.5 llama.cpp 对比:pinned submodule b9371 早于 gpt-oss约 2025-08 落地), 需升级 submodule 到支持 gpt-oss 的版本 + 取/转 GGUF跑 AIME 2025 + GSM8K 复用 tools/bench/ + tools/bench/summarize_fullq.py已有PP 阶段写的)。

7. 复用 Phase 18 的资产

  • 多卡:--pp N(已验证),crates/xserv-distributedNCCL P2P + AllReduce
  • benchtools/bench/runner.py(支持 --pp/--tp)、summarize_fullq.pytools/pp_quality_full.shxserv 0-3 ‖ llama 4-7 并行跑 AIME+GSM8K 的范式可直接改用)。
  • 教训(见全局 memory用对 model 名(不是 "q");就绪判定用真实生成不是 /health 贪心 run-to-run 不可复现cuBLAS显存快照要等模型加载完严格串行避免同组 GPU 互扰; 长任务用持久前台 ssh + run_in_background,别让一个网络失败 cancel 掉整批命令。

8. 重启后立即要做checklist

  1. ssh dash5 hostname 确认 GPU 机可达(不行就问用户新地址 / 改 ~/.ssh/config
  2. git -C ~/projects/xserv log --oneline -6 确认 PP 5 个 commit 还在 859c0cc.. 那串,分支 phase18-pipeline-parallelism)。
  3. ls -la ~/models/gpt-oss-20b/ 看下载进度续传缺的分片§2
  4. 重新 pip download transformers 取参考源码(/tmp 已清)。
  5. 从 §6 的 P19.1 接着干。