01 · 阶段总览从 2B 到 8B 再到 MoE一句话本篇是整条 CUDA 后端迁移线的骨架——先在 2B 上打通「透明加速」放大到 8B 检验可扩展性再转向 30B-A3B MoE 重构 FFN 路径后续每一篇都是对这里某一条的展开。前置无本篇是系列第一篇。环境RK3588ARM CPU 基准/ x86-64 NVIDIA RTX 5090CUDA 后端sm_120· 模型从 Qwen3-VL-2B q8 → Qwen3-VL-8B q4 → 30B-A3B MoE。一、问题与结论一句话路线先在 2B 上打通「透明加速」的骨架 → 放大到 8B 检验可扩展性 → 转向 30B-A3B MoE 重构 FFN 路径。理由2B 足够小、能快速迭代8B 是 dense 的中间规模30B-A3B 是目标形态稀疏专家。每一步都在前一步的骨架上加结构不推倒重来。各个阶段兑现的主指标全部为实测口径见下阶段主指标值篇一 · 2Bprefill 32 token268 → 51 ms5.25×02–06一 · 2Bdecode43 → 20 ms/tok2.15×05、06二 · 8B可扩展性结构不失效产物版本成硬约束07三 · MoEdecode18 ms/tok56 tok/s≈4.1×08四 · KV复用对拍diff0PASS整份 dump 逐字节相同19–21五 · 27Braw-q4 单核47×23贯穿全程的一条实现约定是「透明加速」的落地方式——宿主侧只认一个返回值1 已在 GPU 上完成0 调用方自己跑 CPU/* 文件src/npu/cuda/vllm_cuda.cvllm_cuda_gemm_gw节选 */intrcc-api.dev_gemm_gw(c-dev,out,Aq,a_scale,Wq,b_scale,M,N,K,G,prec,wkey);return(rc0)?1:0;/* 设备层 0成功 → 宿主层 1已加速 */而「每个权重一次」的上装成本则被搬到模型加载期一次性付清/* 文件src/model/vllm_safetensors.cst_cuda_preload_all节选 */{constchar*egetenv(VLLM_CUDA_INFER);if(!e||!e[0]||e[0]0)return0;/* offload off: nothing to warm */}{constchar*egetenv(VLLM_CUDA_STREAM);if(ee[0]atoi(e)0)return0;/* 驻留窗口模式跳过全量预热 */}二、阶段一 · 2B 稠密Qwen3-VL-2B q8目标让引擎「有 GPU 加速、无 GPU 逐字节零回归」且不转换模型格式。建的东西→ 对应篇目组件篇独立运行期模块边界CRT 隔离、透明降级02复用宿主 strip-cache 的权重路径 设备端转置03分组量化 GEMM 内核z-split 一次 launch04卸载集合 投影融合05VRAM 驻留窗口06撞到的问题与解决#问题解决①nvcc 在 Windows 只能用 MSVC 宿主编译器与引擎的 MinGW CRT不可链接CUDA 层做成纯 C ABI 独立模块运行期加载②小投影单独卸载反而更慢QKV 6.39→7.24FLOP 门槛1e7 投影融合QKV/gateup③lm_head走非批式路径压根没被卸载补挂钩 → 6.31→0.39 ms/tok④不预热时上装成本吃掉首次 prefillprefill 净慢于 CPU模型加载后全量预热0.36 s / 253 条⑤预算不足 →静默退化成边跑边重建20→190 ms/tok显式WARNING: only N/M weights stay resident⑥驻留窗口驱逐未来层→ 每 token 全量重传代价对 keep 平坦只驱逐过去层⑦驱逐用cudaFree设备同步抖动比省下的重传还贵设备缓冲池同几何复用②③⑥⑦ 都是反直觉的直觉说「全都卸载」「驱逐就省显存」实测说不是。这四条的完整实测见 05 与 06。结果2B Q8--stream-test --stream-n 16实测CPUCUDA预热融合倍数prefill 32 token268 ms51 ms5.25×decode43 ms/tok20 ms/tok2.15×端到端 (3216)956 ms371 ms2.58×配套验收--cuda-selftest6/6 PASSmax 误差 ≤1.5e-08VLLM_CUDA_VERIFY1全量对拍0 失败greedy TOKIDS 前11token 逐位相同第 12 token near-tie 翻转。三、阶段二 · 8B 稠密Qwen3-VL-8B q4目标把骨架放大到 36 层 / dim4096 的 dense 模型检验可扩展性。撞到的问题→ 详见 07#问题处理⑧8B VQF 布局标志0x1vs 引擎期望0x3→无法加载识别为「产物/引擎版本不同步」需重转换⑨预算参考值从 2B 的 ~1.4 GB 抬到 8B 的~7 GB双侧宿主/显存都必须显式配足结果⚠8B 的 CUDA 实测数据本仓库缺失待补缺口在 07 显式标注不写未实测数字。阶段二的真正收获是方法论层面的骨架在规模上不失效但模型产物版本管理第一次成为硬约束⑧并在阶段三以更重的形式再次出现。四、阶段三 · 30B-A3B MoE目标FFN 从稠密变成稀疏专家——每 token 只激活 8/128 个专家FFN 路径要重构。建的东西→ 对应篇目组件篇MoE 专家权重显存驻留raw q4 直读跳过 strip-cache08设备端 router / top-k / softmax 专家 gate/up/down 内核08full-GPU decode每 token 只 1 次 H2D 1 次 D2H09对拍三层口径 激活精度对齐int8 → float / s1611撞到的问题与解决#问题解决⑩专家权重 16 GB 级走 strip-cache 要在宿主侧全量 int8 解包改成raw q4 直读设备端解 4x4 tile⑪dense FFN 分支不适用于 MoEdecode 循环按is_moe分叉router→top-k→专家 gate/up→swiglu→down 加权聚合⑫int8 激活误差在48 层MoE 上复利累积破坏 greedyMoE FFN 改s16 激活步长缩小 256×⑬d_moe_router是float *却按字节偏移做指针加法 → 4× 越界覆盖 QKV 权重缓存强转(uint8_t *)决定性 bug见 10⑭prefill 首 token 输出 320错误与 ⑬ 同源随 ⑬ 一并修复⑮prefill offload 的 int8 激活使 PPL 差10 倍Δ3.0% vs decode 的 Δ0.33%prefill 也改 float 激活复用同一内核 → Δ0.19%⑫⑮ 是同一根因的两次表现激活量化的误差随规模放大。⑬⑭ 是同一根因的两个症状一个越界覆盖两处缓冲区。结果实测指标GPUCPU结论decode18 ms/tok56 tok/s74 ms/tok13.5 tok/s~4.1×prefill 32 tok45–55 tok/s36 tok/s加速greedy 前 16 token与 CPU 逐位一致—16/16CORPUS_NLLfull-decode5.4725.490Δ0.33%CORPUS_NLLprefillfloat 激活5.4805.490Δ0.19%设备口径NVIDIA GeForce RTX 5090 sm_12031.8 GiB权重缓存预算 15495 MB。另外做了一次量化边界判定MoE 专家权重能否降到三值{-1,0,1}1.6bit以原始权重为 oracle、6.04 亿元素实测重建误差量化bpwSQNRQ4_0主线4.5021.03 dBTQ2_0三值1.581.73 dB额外损失—19.30 dB判否——三值只适用于冗余查表不适用于承载精度的权重详见 12。五、阶段四 · KV 缓存迁移到 GPU调度侧目标把 KV 复用 / 前缀共享 / L3 恢复这些调度侧能力也搬到 GPU 侧镜像上让「GPU 算得快」不只体现在单条序列上。#问题解决篇⑯单份 KV 镜像 kv_initfree-all ⇒ 多 state 互相踩per-state 槽位池vc_kv_bind指针视图19⑰前缀复用时的 D2D 同步缺口同类静默分叉共三处统一走vc_kv_bind 同步19⑱disk-KV 恢复类路径 × 镜像可达性未证伪就补丁先证伪可达性 → 结构性封堵门优于补丁20结果实测地雷diff-1.213e01 FAIL→ 修后diff0.000e00 PASSL2 复用对拍10070 key 0 不等且整份 dump 与基线逐字节相同DKVTEST 从logits_equalFAIL→PASS。另外做了一次收益区间实测界定KV 分页 / GPU 侧 L3 驻留的两个候选——镜像单槽396 MiB占峰值余量的 1.2%门禁直接判不作见 21。**「先量化收益上界再决定投入」**是阶段四最重要的方法论产出。六、阶段五 · 混合架构 Qwen3.5-27B进行中目标换一个混合架构模型——64 层 48 层 Gated DeltaNet 线性注意力 16 层 full attention。这一阶段的两处「新」是算子族与层结构同时变前四阶段是无状态 GEMM / attention这里第一次出现有状态递推算子含递推状态镜像与 conv 历史。#问题解决篇⑲既有 dense cache 存 int81 B/参数27B q4 常驻膨胀到 ≈30 GB 31.8 GB新增raw-q4 直读的 dense 内核 独立常驻池rq_*23⑳有状态递推算子首次上 GPU并行怎么切、判据用什么、状态怎么镜像先f32 档把七步算子序列钉死再切 q4状态镜像 gdn_reset24㉑整层对上了、整模型对不上逐级下钻整层 → 相 → 单核微基准 → 落到访存粒度25㉒「发射空档」量了三次、前两次口径都不对逐相事件计时 → nsys →stream−graph 判别实验26㉓空档 主机 CPU ≈5 µs 与设备地板 ≈1.1 µs取大者「少发一次」S 常驻寄存器 β/a 融合发射27㉔对拍工具能跑、src/里零调用接进引擎主循环键约定统一到引擎侧28㉕serve HTTP 200 却有输出是回显根因不在代码模型目录里混进了别的模型的vocab.bin28㉖graph 化时「随 token 变化的位置量」被钉成常量把 RoPE 位置 / KV 行号搬到设备d_dyn29㉗「融小核」的天花板是在 stream 档算的graph 落地后已作废在 graph 档重量 ⇒性价比不成立暂缓29㉘投影的 cold→bulk 缺口 ≈2.9 ms但是设备侧粒度还是主机侧发射未定--gran判别graph 只抬 4.4%、合并能抬 15% ⇒ 合并发射29㉙「逐字节相同」是整合级证据证不到死代码分支r1/r20、cols%256!0抽唯一一份源 9 形状内核级直测含 4 个合成死代码形状29㉚以为 S4MTP 投机只是「接线」实际卡在hybrid 没有批量前向先量接受率G1α₁ 65.7%、E[len] 2.107⇒ 值但要先造底座29㉛收益表里藏着一个从没量过的比值把「Mk1 一次前向」当成单 token 成本G2 形状级探针朴素1.76×/ 地板1.15×⇒ 收益订正为1.06–1.51×29㉜「让 x 复用」撞上一条已退役负结果同动机、试过回退R 行/warpM1 对照复现负号、M4翻正2.30→2.93⇒ 收益收窄为1.32–1.51×29㉝三条门禁过了但大工程不能靠「按计划」三个字开工把 S4b 冻成工单三件能力 每形状 R 表 三步落地第一步零行为变化 G3 门禁 回退29㉞MTP 头模型内草稿头没有官方 oracletransformers直接忽略mtp.*基准 官方算子类 内部 wiring 转录写清「能证/不能证」四个口径点逐条核到源码30结果阶段五已兑现的部分实测指标值篇raw-q4 单核 vs CPU 融合47×630.8 vs 13.4 GMAC/s23GDN f32 档对 oracleworst max_rel 3.800e-07判据 1e-424整模型异构 decode 端到端maxrel 3.4e-06/36.8 tok/s25访存粒度#0①端到端1.44×25发射空档nsys 直接量每 token2.40 ms12.3%26S 常驻寄存器S5i18.83 → 16.41 ms/token 1.148×27β/a 融合发射S5j16.528 → 15.875 ms/token 1.0411×27CUDA Graph 接到 hybridS5l15.944 → 14.066 ms/token 1.1335×29同输入多投影融合#0③15.928 → 14.400 ms/token 1.1062×graph 档 1.0892×29serve HTTP 端到端200中文题tok_s47.43词表 248077 /im_start24804528MTP 头模块级对拍11 组 × 5 token 全 PASSexpectmax_rel 1.5e-6~3.4e-6基准为自造30MTP 接受率S4a真实 hiddenα₁0.657、E[len]2.107T169, k429阶段五与前四阶段最大的不同性能优化的对象从「算得更快」变成「发得更少」。到 S5k 之后单核已经逼近访存上限剩下的收益全在发射次数与位置量设备化上。七、问题台账一~五阶段一页总览#阶段问题一句话解法篇①2BCRT 不可链接独立纯 C 模块02②2B小投影卸载更慢FLOP 门槛 融合05③2Blm_head 没挂钩补非批式路径挂钩05④2B不预热 prefill 变慢加载期预热05⑤2B预算不足静默退化显式 WARNING05⑥2B驱逐未来层 → 全量重传只驱逐过去06⑦2BcudaFree 同步抖动缓冲池06⑧8B布局标志不匹配重转换产物07⑨8B预算抬到 ~7 GB双侧配足07⑩MoE16 GB 宿主解包raw q4 直读08⑪MoEdense FFN 分支不适用按 is_moe 分叉08⑫MoEint8 激活破 greedys16 激活08 / 11⑬MoErouter 指针越界覆盖权重(uint8_t *)强转10⑭MoEprefill 首 token 320同 ⑬10⑮MoEprefill PPL 差 10 倍float 激活11⑯KV单份镜像 free-all 互踩per-state 槽位池19⑰KV前缀复用 D2D 同步缺口统一vc_kv_bind19⑱KV恢复类路径未证伪就补丁先证伪可达性门优于补丁20⑲27Bint8 展开装不下≈30 GBraw-q4 直读 独立常驻池23⑳27B有状态递推算子首次上 GPU先 f32 档钉死算子序列24㉑27B整层对上、整模型对不上逐级下钻到单核访存粒度1.44×25㉒27B发射空档量了三次stream−graph 判别实验26㉓27B空档取大者主机 5 µs / 设备 1.1 µs少发一次S 常驻 β/a 融合27㉔27B工具能跑、引擎零调用接进主循环 键约定统一28㉕27BHTTP 200 却是回显模型目录混了别的词表28㉖27B位置量被 graph 钉成常量搬到设备d_dyn29㉗27B「融小核」的天花板是 stream 档算的graph 落地后作废在 graph 档重量 ⇒ 性价比不成立暂缓29㉘27B投影 cold→bulk 缺口 ≈2.9 ms成因未定--gran判别 ⇒ 合并发射29㉙27B「逐字节相同」只是整合级证据边角分支在真实模型里是死代码抽唯一一份源 9 形状内核级直测29㉚27BS4MTP 投机被当成接线活实际卡在 hybrid 没有批量前向先量 G1 接受率 ⇒ 值得做先造底座29㉛27B收益表里有个从没量过的成本比值G2 探针 ⇒ 收益订正为 1.06–1.51×29㉜27B「让 x 复用」与一条已退役负结果同动机R 行/warpM1 复现负号、M4 翻正 ⇒ 收益 1.32–1.51×29㉝27B门禁过了但大工程缺一份冻结的工单S4b 工单能力 每形状 R 表 三步落地 门禁 回退29㉞27BMTP 头没有官方 oracle且口径点写反了也「跑得动」自造基准 说清能证/不能证逐级快照定位30八、贯穿五个阶段的主线透明性CUDA 层的存在与否不改变引擎行为模块缺失 → 逐字节等价。这条从①贯彻到底。实测界定卸载集合、融合范围、驻留档位、激活精度——没有一项是「全都上」或「凭直觉」全部由分桶实测选出②③⑥⑦⑫⑮。产物版本同步模型产物VQF 布局标志、MoE 专家 raw q4、模型目录里的vocab.bin必须与引擎版本一起演进⑧⑩㉕。阶段五的那次回显事故是这条主线的极端形态代码全对、数据错了。「发得更少」与「位置量设备化」阶段五新增当单核已逼近访存上限收益就从「算得更快」转到「少发一次」㉓与「把随 token 变化的量从内核参数赶出去」㉖。同一条 CUDA Graph 开关在两个负载下符号相反——launch-bound 档正收益、计算受限档负收益。九、边界与未兑现边界前四阶段的性能实测基本都在RK3588 CPU 基准 vs RTX 5090 CUDA 后端这条口径上换设备需重测。8B 阶段的 CUDA 性能数据缺失见 07本总览不写未实测的 8B 数字。「位数一致」「逐字节相同」这类结论都有明确的作用域整合级 vs 内核级、本后端内 vs 与 CPU 之间不能互相外推。未兑现/已收口的项Tensor Core★已在 prefill 上落地见 55 篇decode 侧未接。尚未做投机解码接入 CUDA、MoE FFN tiling、batch decode、prefill attention offload、KV 4bit、多 GPU EP。阶段五侧S4 MTP 投机—— ★判否收口设备化正确、判据 2 位级过收益 0.531×–0.737×借鉴评估三条候选全否唯一开口「每轮产出口径」已偿清 ⇒ 见 45 / 46。graph 未接 prefill—— ★该项作废订正CUDA 路径的 prefill 就是逐 token 循环同一model_step早已被 graph 覆盖。与CPU的位级一致有意不做。★另记一项历史「跑不了」已翻正第 45 篇 写的「本机不可跑llama.cpp」CPU-only 构建 无 27B GGUF是对当时成立的时点断言已补 CUDA 构建 27B GGUF 并做同卡对拍decode1.12×/ prefill≈15.4×不归因/ llama.cpp自带 MTP 1.92×⇒ 见 47。★那个 15.4× 已被追到 ≈4.6×见 50–55 篇。prefill 微优化线收口见 48该项已判否 候选根因被 Phase 0 推翻GDN 仅 ~12%四条廉价路径逐条实测关闭S1x smem位级 PASS 但引擎配置不提速 ⇒不投入当时写的「天花板 ≈4.7× llama.cpp 15.4×⇒ 追平须非位级重写」——★那条「非位级重写张量核」后来真的做了→902 t/s / ≈4.6×。投机解码 Phase 0 已毕 Phase 1 收口见 49该项已判否 H2 证伪GDN 占档B 5.67%/H3 有界重放 36%归零 0.88×/H1 主导每轮接受 0.833 vs llama.cpp 1.385Phase 1逐位置0.357 vs 0.808、真实前缀0.604、同流 0.600⇒排除「流」⇒收口为「不可廉价翻正」。prefill 追赶见 50–55 篇把15.4× 拆账GEMM18.5× GDN 11.6× ⇒ 先打 GEMM→ 两条廉价路径关闭占用率 / dp4a→位级 M 16→32 ⇒ 273 → 369 t/s1.35×差距 11.3×→ 张量核探针fp16 融合4.45–4.76× /RMSrel 2.65e-4→ ★口径反转引擎粒度是N≤32⇒块宽是主杠杆→接线落地门关逐字节不变 门开A1b/A2/A4 全过 A3 5/5 文本逐字同⇒prefill 512 372 → 902 t/s2.42×对 llama.cpp ≈4.6×。★ 副产品同源两次构建 DLL SHA 不同⇒ 禁用 SHA 当判据。★阶段五开放项两项prefill 微优化、投机解码 Phase 0/1均已判否 另一项KV 载入相关为唯一进行中phase ① 接线已落地 / phase ② 开门采数未放行。两条「验证欠账」已补测收口见 29 第十节融小核暂缓性价比不成立小投影 fusion 已落地prefill 批量化已落地且默认开。清单与验收标准见仓库wiki/CUDA迁移计划与验收.md。CPU 对照迁移前基线CPU 参考kestrel-llm/src/model/vllm_safetensors.c函数dyn_matvec_q8/dyn_matvec_q4_q8—— 引擎的 CPU 回退路径逐行反量化 q8/q4 权重做点积算 logits。迁移要点CPU 侧由引擎自跑矩阵乘 → CUDA 侧改成宿主只认一个返回值1已在 GPU 完成、0调用方自己跑 CPU每个权重一次的「上装」成本从每步搬到加载期预热骨架每步加结构、不推倒重来。真机验证命中 E1E2-Cuda构建成功 --cuda-selftest6/6 PASSGPU-CPU 误差 ~1e-8阶段一 2B/MoE 的端到端倍数5.25×/2.15×/4.1×为文中记载不在本轮证据内。十、小结可复用结论骨架先行、逐步放大2B 打通「透明加速」的最小闭环8B 只验证规模不失效MoE/混合架构再改结构——每一步都在前一步上加结构不推倒重来。透明性是底线CUDA 层缺失时行为与引入前逐字节一致这条从阶段一贯彻到底是所有其它优化的前提。一切由实测界定卸载集合、融合范围、驻留档位、激活精度没有一项是「全都上」或凭直觉——都被分桶实测选出来过。产物版本要和引擎一起演进VQF 布局标志、专家 raw q4、甚至模型目录里的词表——代码全对、数据错了同样会「跑得动但错」。到后期优化对象从「算得快」转向「发得少」单核逼近访存上限后收益在减少发射次数与位置量设备化上。相关篇目第 02 篇 · 架构边界、第 07 篇 · 8B 阶段、第 08 篇 · MoE 专家权重显存驻留源码与配套资源本仓库 https://gitee.com/pei-xiaoguang/kestrel-llm-cuda.gitCPU 推理源码 https://gitee.com/pei-xiaoguang/kestrel-llm