Nanoflow
通过纳米批次并行调度将GPU利用率提升至80%以上,吞吐量最高达TensorRT-LLM的1.91倍
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
通过纳米批次并行调度将GPU利用率提升至80%以上,吞吐量最高达TensorRT-LLM的1.91倍
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
当一家 AI 创业公司需要同时服务数十万用户、却发现 GPU 利用率始终卡在 30% 以下时,工程师们通常会陷入两难:升级硬件太贵,优化框架太难。正是在这样的背景下,ETH Zurich 的 efeslab 团队推出了 NanoFlow——一个将 GPU 利用率压榨到极致的高性能 LLM 服务框架。与 vLLM、DeepSpeed-FastGen、TensorRT-LLM 等主流方案相比,NanoFlow 在离线吞吐量场景下最高实现了 1.91 倍的性能提升,而这一切的实现手段,是一项名为"设备内并行"(Intra-Device Parallelism)的底层架构创新。
LLM 推理的本质是一系列计算与内存操作的交替执行:矩阵乘法(compute-bound)、注意力计算(memory-bound)、KV-Cache 读写(memory-bound)、集合通信(network-bound)。传统框架通常采用流水线设计,将这些操作按顺序串联执行——一个操作完成后才启动下一个。这种设计在单个请求场景下表现良好,但在高并发场景下,流水线的"气泡"(bubble)会不断积累:当 GPU 在等待 KV-Cache 从显存加载时,张量乘法单元实际上处于闲置状态;反之亦然。
efeslab 团队在一篇 OSDI'24 论文中指出,现有框架的资源利用率普遍偏低,原因是不同类型的操作在时间维度上存在大量重叠窗口。他们的解法是:nano-batching——将单个请求的推理过程拆解为更细粒度的"纳米批次",让 compute-bound 和 memory-bound 操作在同一个 GPU 内核中交错执行,从而在时间轴上实现真正的并行而非串行。
图1:NanoFlow 核心架构 — 设备内并行调度示意图
NanoFlow 的核心创新在于将传统上按批次(batch)为单位的工作调度,改为以纳米批次(nano-batch)为单位的细粒度调度。每个纳米批次包含少量请求(如 4-8 个),框架会分析当前 GPU 各执行单元的状态,动态选择最优的操作序列:
图2:纳米批次并行原理 — compute/memory/network 操作在时间轴上重叠
以 Llama2-70B 在 8xA100 上的离线推理为例:传统框架在 1024 输入 / 512 输出设定下,GPU 的张量乘法单元实际利用率不足 40%。NanoFlow 通过纳米批次调度,将利用率提升至 80% 以上,直接反映为吞吐量 1.5-1.9 倍的提升。
GPU 利用率提升后,CPU 端的调度开销(KV-Cache 管理、批次组成、请求退出选择)反而成为新的瓶颈——实验显示这部分开销占比超过 10%。NanoFlow 的解法是异步控制流:在第 i 次迭代尚未结束时,CPU 已提前为第 i+1 次迭代准备批次信息和 KV-Cache 分配;请求退出判定也被推迟到 i+2 次迭代才执行,从而将 CPU 与 GPU 的时钟周期彻底解耦。
图3:异步 CPU 调度 — CPU 在 GPU 执行期间并行准备下一次迭代
对于多轮对话场景,NanoFlow 还实现了 KV-Cache 的 SSD 分级存储策略:已完成请求的 KV-Cache 会立即卸载到 SSD 以释放显存,而不是等待显存紧张时才被动驱逐。实验表明,服务 LLaMA2-70B 所需的 SSD 卸载带宽仅需 5GB/s,而一块消费级 NVMe SSD 即可提供 3GB/s 的持续带宽,完全满足需求。
efeslab 团队在 A100 80GB SXM 服务器上(8卡),以 vLLM v0.5.3、DeepSpeed-FastGen v0.2.3、TensorRT-LLM v0.8.0 为基线进行了系统对比评测。所有框架均关闭了量化、投机解码、前缀缓存等特定优化,确保公平比较。
离线吞吐量测试(输入 1024 / 输出 512,LLaMA2-70B):
图4:离线吞吐量 — NanoFlow 在 ShareGPT、LMSYS-Chat-1M、Splitwise 三种真实trace下全面领先
在 ShareGPT 真实对话数据下,NanoFlow 的吞吐量比 TensorRT-LLM 高出 91%;即使与 vLLM 相比也有 1.5 倍以上的优势。
在线延迟测试(归一化延迟 = 端到端延迟 / 输出 token 数):
图5:在线延迟 — 相同延迟下 NanoFlow 可支撑更高的请求率
多模型可行性验证:
图6:NanoFlow 在 Llama2-70B、Llama3-70B、Qwen2-72B 等多个模型上的吞吐量表现
NanoFlow 的代码库规模约 4000 行,采用 C++ 高性能后端 + Python 演示前端的架构:
核心模块:
core/ — 核心调度引擎:executor(执行器)、worker(工作线程)、nanobatchSplit(纳米批次切分)、weightManager(权重管理)、bufferAllocate(显存分配)operations/ — 算子集合:GEMM(CUTLASS)、Attention(FlashInfer)、Embedding、AllReduce/AllGather(MSCCL++)、RoPE、Norm、Samplingentry/ — 入口脚本:run_llama3.py、easy_test.py、compare.pyauto_search/ — 自动调优:基于 Profiling 的配置搜索models/ — 模型配置:Llama3-70B/8B、Qwen2-72B 等多种模型定义第三方依赖:
NanoFlow 集成了 NVIDIA 官方的高性能计算库:CUTLASS(GEMM 算子)、FlashInfer(注意力内核)、MSCCL++(多卡集合通信)。这些库的组合确保了底层计算的高效率。
必须直说的是,NanoFlow 并不是一个"一键部署"的项目。它面向的是有 HPC 背景的团队,典型用户画像是:拥有多卡 A100/H100 服务器、熟悉 CUDA/GDRCopy、了解 NCCL/InfiniBand 网络配置的 AI 系统工程师。
部署流程包括:conda 环境搭建、Gurobi 许可证配置(学术用途免费)、CUTLASS/FlashInfer/MSCCL++ 第三方库从源码编译、CUDA 12.x + Nsight Systems 工具链安装、以及多卡场景下的 NCCL 配置和共享存储挂载。官方提供了 setup.sh 脚本,但实际运行中仍可能遇到库版本兼容性问题。
没有 Dockerfile 是最大的遗憾——对于希望用容器快速验证的团队而言,这是一个明显的缺失。项目依赖的 Gurobi 是商业求解器,也增加了容器化的复杂度。
NanoFlow 的出现代表了 LLM 服务优化从"框架层"向"内核层"的深入。当前主流的 vLLM 和 TensorRT-LLM 已经将许多工程优化做到了极致,但 NanoFlow 通过对 GPU 执行单元级别的细粒度调度,证明了仍有可观的性能空间。
最佳适用场景:
不太适合的场景:
该论文已发表于 OSDI'24,arXiv 地址:https://arxiv.org/abs/2408.12757