在 魔改 3080 20G上,运行当下流行的ninfer-3090代码,峰值70t/s,ctx70k
-
对代码有一定的修改以适配RTX3080 代码仓库
====================
修复的 bug
文件 问题 修复 src/ops/gdn_gating_proj/bf16/bf16_gdn_gating_proj_plan.cpp协作式 MMA 路由上界按 82 SM 硬编码,68 SM 上 prefill 宽 768 时 144 CTA 超出 136 驻留预算,模型加载即抛 candidate is not legal for exact problem路由上界改为按运行时 device_sm_count()动态推导src/ops/linear_swiglu/nvfp4/nvfp4_linear_swiglu_plan.cppA16 融合 swiglu 仅注册到 T≤16,prefill 宽 >16 即抛异常 在 token 轴上按 32 分块调用小-T 核(镜像 FP8 A16 路线) src/ops/linear_swiglu/nvfp4/nvfp4_linear_swiglu_small_t.culauncher 只注册 2..16 扩展到 2..32,与线性小-T 生产 schedule 一致 多角度优化结果
指标 nvfp4 A16(原) groupwise-int(推荐) 提升 权重显存 16.03 GiB 15.25 GiB −0.8 GiB prefill(长 prompt) 19.4 tok/s 558–636 tok/s ~29× decode(贪心) 11.7 tok/s 33.7 tok/s 2.9× decode(MTP3) 33.0 tok/s 69.5 tok/s 2.1× 投机解码:MTP3 最优(87–91% 接受率);draft=5 反降至 67.6 tok/s(接受率 73%)。
KV 量化
选项 payload(2048 tok) 可用性 bf16 128 MiB 可用 int8-group64 66 MiB 可用(推荐,显存最低) fp8 — sm_86 拒绝(需 Blackwell mma.f8f6f4) rk8v4(q4 V) — 拒绝(未移植到 kv_cache_appendOp)70K 上下文长任务测试
配置:
groupwise-int+--kv-dtype int8+--spec mtp --draft-tokens 3,prompt 69,770 token。指标 结果 prompt tokens 69,770 prefill 636 tok/s(109.7 s) decode(MTP3) 62.97 tok/s(91% 接受率) decode(贪心 baseline) 28.66 tok/s KV payload 2.41 GiB free after startup 625 MiB 对比 20-token 上下文:MTP3 从 69.5 降到 62.97 tok/s,仅 ~9% 退化,注意力随上下文增长的成本被 int8 KV 有效控制。
-
对代码有一定的修改以适配RTX3080 代码仓库
====================
修复的 bug
文件 问题 修复 src/ops/gdn_gating_proj/bf16/bf16_gdn_gating_proj_plan.cpp协作式 MMA 路由上界按 82 SM 硬编码,68 SM 上 prefill 宽 768 时 144 CTA 超出 136 驻留预算,模型加载即抛 candidate is not legal for exact problem路由上界改为按运行时 device_sm_count()动态推导src/ops/linear_swiglu/nvfp4/nvfp4_linear_swiglu_plan.cppA16 融合 swiglu 仅注册到 T≤16,prefill 宽 >16 即抛异常 在 token 轴上按 32 分块调用小-T 核(镜像 FP8 A16 路线) src/ops/linear_swiglu/nvfp4/nvfp4_linear_swiglu_small_t.culauncher 只注册 2..16 扩展到 2..32,与线性小-T 生产 schedule 一致 多角度优化结果
指标 nvfp4 A16(原) groupwise-int(推荐) 提升 权重显存 16.03 GiB 15.25 GiB −0.8 GiB prefill(长 prompt) 19.4 tok/s 558–636 tok/s ~29× decode(贪心) 11.7 tok/s 33.7 tok/s 2.9× decode(MTP3) 33.0 tok/s 69.5 tok/s 2.1× 投机解码:MTP3 最优(87–91% 接受率);draft=5 反降至 67.6 tok/s(接受率 73%)。
KV 量化
选项 payload(2048 tok) 可用性 bf16 128 MiB 可用 int8-group64 66 MiB 可用(推荐,显存最低) fp8 — sm_86 拒绝(需 Blackwell mma.f8f6f4) rk8v4(q4 V) — 拒绝(未移植到 kv_cache_appendOp)70K 上下文长任务测试
配置:
groupwise-int+--kv-dtype int8+--spec mtp --draft-tokens 3,prompt 69,770 token。指标 结果 prompt tokens 69,770 prefill 636 tok/s(109.7 s) decode(MTP3) 62.97 tok/s(91% 接受率) decode(贪心 baseline) 28.66 tok/s KV payload 2.41 GiB free after startup 625 MiB 对比 20-token 上下文:MTP3 从 69.5 降到 62.97 tok/s,仅 ~9% 退化,注意力随上下文增长的成本被 int8 KV 有效控制。
几个修复都对口,尤其 82 SM 硬编码那处——3090 是 GA102 82 SM,3080 20G 是 68 SM,路由上界改成 device_sm_count() 是正解,这类硬编码在移植时最容易踩。
更关键的是量化路线的选择:sm_86 没有原生 FP4,nvfp4 在 Ampere 上基本是模拟/回退,所以 prefill 19.4 tok/s 不奇怪;换 groupwise-int 走 INT4 tensor core 才有 29× 这个量级。这条对想抄 3090 代码上 3080 的人最重要。
问两个参数:groupwise-int 的 group size 用了多少(64 还是 128)?kernel 是 dequant 到 fp16 再算,还是真走 mma INT4?前者省显存但吃带宽,后者才能在 3080 的 760GB/s 上把 decode 拉起来。
提醒一句:free after startup 只剩 625 MiB,ctx 再长或并发大于 1 很容易 OOM,建议先把 max-running-requests 锁 1,再逐步压 KV。MTP draft=5 掉到 67.6 符合预期,MTP3 在多数模型上就是甜点。
3080 760GB/s 对 3090 936GB/s,decode 63 对 78 基本就是带宽比;配上 91% 接受率,这卡跑 70K 已经压得很干净了。