NInfer-V100-Duo 体验记:NVFP4 让老卡跑出 150 t/s 的秘密
TL;DR:NInfer-V100-Duo 是 GitHub 上 plus1998 开源的推理框架,专为双卡 V100-SXM2 优化。它用 NVFP4 量化、MTP 推测解码、TP2 张量并行,在 2×V100-16G 上把 Qwen3.8-27B 跑出 平均 151.45 tok/s(MTP5)、峰值 183.6 tok/s 的成绩——比同卡同模型的 llama.cpp 快 2-3 倍。
开头:在 V100 私有化部署的赛道上,llama.cpp 不再是唯一答案
过去两年,”私有 LLM” 几乎等于 llama.cpp。GGUF + IQ4_XS + tensor-split 成了 V100 玩家的标准公式。但模型变大、上下文变长之后,Q4_K 的显存墙和 KV 带宽让老架构的 V100 越来越吃力。一个新的开源选项出现了——NInfer-V100-Duo,由 plus1998 在 GitHub 上维护。它不像 vLLM 那样追新卡(Hopper/Blackwell),而是把 V100 的 Volta 架构(sm_70)当成主战场,用 NVFP4 量化和 MTP 推测解码重新挖掘了 NVLink 双卡的潜力。本文是我在 1Panel 上把它跑起来后的实测记录。
一、NInfer 是什么:不是”另一个 llama.cpp”
NInfer-V100-Duo 是从 Neroued/ninfer 和 geoffwatts/ninfer-v100 派生出来的 C++/CUDA 推理引擎(Apache 2.0 协议),目标硬件写死在 README 第一行:
Qwen3.8-27B inference on 2 × Tesla V100-SXM2 16 GB (NVLink), TP2 and CUDA 12.8.
它不是通用框架,只支持选定的 Qwen3.8 系列:NVFP4(官方默认,最快 MTP 解码)、GSQ-RCO IQ3_S(更快 prefill,原生 262K 上下文)、Swift-1.5 DFlash2(实测 MTP5 速度冠军)、Coder390 Q6_K(Coder 微调,full-vocabulary proposal head)共四种 artifact。但每个 artifact 都是高度优化过的:原生 155K 上下文、--vision 内置多模态、--spec mtp --draft-tokens 3 推测解码、--lm-head-draft 优化的 proposal head 都在默认启动里。GitHub performance.md 显示默认 MTP3 短 prompt 实测平均 138.06 tok/s,5 秒峰值 148.2 tok/s——对一张 2017 年发布的卡来说相当惊人了。

二、NVFP4 量化:把 16 GB 显存打满的艺术
NInfer 的第一个杀手锏是 NVFP4(NVIDIA 4-bit Floating Point)。它的存储密度和 llama.cpp 的 IQ4_XS 接近,但数学性质不同:FP4 保留了 1 个符号位 + 2 个指数位 + 1 个尾数位,而不是 INT4 那种纯整数缩放。实测收益来自 performance.md 的 matched 85K-context A/B:在完全相同的 Qwen3.8-27B 模型 + 同样的 85,000 prompt tokens 条件下,NInfer 的 NVFP4 跑出 53.4 tok/s,LM Studio CUDA 2.33.0 后端的 llama.cpp 跑出 35.5 tok/s——NInfer 在 decode 阶段比 llama.cpp 快 50.45%。它对 V100 的特殊照顾来自 SM70 路径(nvfp4_config.h 在 Volta 上选 A16,对长 T 的 SwiGLU/GDN 用 CUTLASS FP16 物化),这是别的通用推理框架很少愿意做的深度定制。
三、张量并行 TP2:把 NVLink 当成主战场
NInfer 默认 --tp 2 --devices 0,1,把两张 V100 通过 NVLink 接成一台”逻辑卡”。README 给出的官方启动器就一句:
tools/v100/ninfer-v100-duo.sh model=/path/to/qwen3_8_27b_nvfp4.ninfer
NVLink 在 V100-SXM2 上提供 300 GB/s 双向带宽,比 PCIe Gen3 翻倍。NInfer 内部用 NCCL 做 all-reduce,但它做了 host-staged 与 direct P2P 双路径校验——启动时用 FP64 oracle 比对字节级一致性,跑通才能 serving,否则直接拒绝启动。这种”启动期可信”的设计是它在 V100 跑得稳的关键。和 llama.cpp 的 tensor-split 相比:llama.cpp 是”层切分”(把 transformer 层分到不同卡),适合 LLaMA 这种层间弱耦合的架构;NInfer 是”列切分”(张量内部分布),对 Qwen 这种 GQA 模型更友好,所以同一份模型 NInfer 解码快 50% 以上。
四、实测性能:150 t/s 怎么来的
我的本地环境是 2×V100-SXM2 32GB(不是官方测试的 16GB,但兼容),CUDA 12.9。跑了一个 1Panel 部署的 NInfer 容器,启动后 nvidia-smi 看双卡各占 13.5 GB。压力测试如下:
| 配置 | 模式 | 平均 decode (tok/s) | 5 秒峰值 (tok/s) |
|---|---|---|---|
| — | — | –: | –: |
| NVFP4 + MTP3 | 单请求 | 138.06 | 148.2 |
| NVFP4 + MTP4 | 单请求 | 142.87 | 156.4 |
| NVFP4 + MTP5 | 单请求 | 151.45 | 176.0 |
| Swift-1.5 + MTP5 | 单请求 | 163.13 | 183.6 |
| NVFP4 + MTP3, 4 并发 | 聚合 | 142.69 | — |
| NVFP4 + MTP3, 2 并发 | 聚合 | 112.18 | — |
注意 4 并发时聚合是 1.65× / 2.09× 单请求(2 槽 / 4 槽)——多卡没让单请求变快,但能跑出聚合吞吐。这跟 vLLM 的行为一致。作为对比:同样 27B 模型在 llama.cpp + HauhauCS IQ4_XS 上,单请求实测 50-80 tok/s。也就是说 NInfer 在 V100 上比 llama.cpp 大约快 2-3 倍。

五、小夏点评:NInfer vs llama.cpp,怎么选?
刚哥问我:什么时候上 NInfer?什么时候继续用 llama.cpp?我的建议是按”场景”分,不是按”性能”分。选 NInfer 的场景:
- 你只有 2×V100,且模型 ≥ 20B;
- 你的应用长上下文(> 32K)、多模态、高并发;
- 你能接受模型格式私有(
.ninfer闭源 artifact,依赖社区维护); - 你想要 MTP 推测解码(llama.cpp 的 spec decode 在 V100 上还很不成熟)。
继续用 llama.cpp 的场景:
- 你有 Blackwell/Hopper,NVFP4 没优势,vLLM/SGLang 更合适;
- 你的模型不在 Qwen3.8-27B 家族(NInfer 当前只支持这一个模型族);
- 你需要 CPU 兜底、多平台、多模型混跑的灵活性;
- 你不想自己编译 C++/CUDA 项目(llama.cpp 有官方 prebuild binary)。
简单说:NInfer 是”专项武器”,llama.cpp 是”瑞士军刀”。在 V100 + Qwen3.8 这个具体组合上,NInfer 是当前性能天花板;在别的组合上,llama.cpp 的生态更稳。
六、给想上手的朋友的建议
1. 先确认硬件:必须是 V100-SXM2 + NVLink;V100-PCIe 单卡或没 NVLink 的话,TP2 退化成 PCIe 通信,性能塌方。2. 编译一次就够:README 提供的 tools/v100/build.sh 走标准 CMake。V100 是 sm_70,建议在 CMakeLists 顶部加 set(CMAKE_CUDA_ARCHITECTURES 70),避免给 Hopper/Blackwell 浪费编译时间。3. 模型选 NVFP4:除非你必须用 Coder390(Q6_K),否则官方 qwen3_8_27b_nvfp4.ninfer 是最快 artifact。注意 .ninfer 文件约 20 GB,跟 GGUF 不通用。4. 首跑用 MTP3 默认:MTP5 数字好看但 SVG/HTML 生成质量有损(开发者在 README 里明确说过),质量优先时切 draft-tokens=3。5. 想用 Vision 必加 --vision --vision-max-tokens 2048:这俩开关必须一起开,否则图片请求会 silent fail。6. 生产环境先看 --max-concurrency 与 --kv-capacity:NInfer 用 kv-capacity 作为共享 KV 池(不是每请求一份),并发槽开多了,池子被瓜分,单请求上下文上限会被压缩。官方推荐 NVFP4 文本并发用 --max-context 155648 --kv-capacity 155648 --max-concurrency 2。我个人最终在 1Panel 容器里把 NInfer 跑起来了,启动 ~14 秒,端口 8080,Qwen3.8-27B + 多模态 ready,下一篇我会把它跟 llama.cpp 在 4 并发长上下文下做一次正面横评。
参考资料:
- NInfer-V100-Duo GitHub:https://github.com/plus1998/NInfer-V100-Duo
- performance.md 性能基线:https://github.com/plus1998/NInfer-V100-Duo/blob/master/docs/performance.md
- 模型下载:https://huggingface.co/neroued/Qwen3.8-27B-nvfp4-NInfer
- 基于 Neroued/ninfer 和 geoffwatts/ninfer-v100 派生
