- 推理引擎
- 大模型
【免费下载链接】FlexGen
Running large language models on a single GPU for throughput-oriented scenarios.
本文以 FlexGen 仓库中收录的论文《High-throughput Generative Inference of Large Language Models with a Single GPU》为核心骨架,结合仓库源码(flexgen/flex_opt.py、flexgen/compression.py、experimental/cost_model.py 等)展开解读。通过本文,你将理解 FlexGen 如何在单块普通 GPU(如 16GB T4)上通过 GPU/CPU/磁盘三级异构聚合、线性规划策略搜索与 4-bit 分组量化,将 OPT-175B 级别的模型吞吐推升至 1 token/s 以上;并掌握
--percent卸载策略、压缩开关、HELM 基准接入与分布式扩展的完整实操方法。
FlexGen 的定位是面向吞吐优先(throughput-oriented)场景的生成引擎:这类任务(批量评测、信息抽取、数据整理、表单处理)需要以批处理方式在数百万 token 上反复运行 LLM,对单次延迟不敏感,但对整段运行时间的 token 吞吐率极为敏感。其核心思想是用 I/O 效率换延迟,在低成本单 GPU 硬件上把批大小做到传统方案无法企及的规模,从而显著提升最大吞吐。仓库 README 同时明确列出了其局限性:作为基于卸载(offloading)的系统,在弱 GPU 上、尤其是小批量场景下,其速度仍远低于拥有足够强 GPU 将整个模型驻留显存的方案,因此它主要针对单 GPU 上的批量处理设置优化。
一、论文核心贡献:为什么单卡能跑 175B 模型
1.1 问题背景:LLM 推理的资源门槛
论文摘要指出,大语言模型推理的传统路径需要多块高端加速器才能可行。而现实中出现了一批延迟不敏感(latency-insensitive)的批量处理任务:公司内部全部私有文档的分类与抽取、HELM 基准上全部任务的跑分等。这类工作负载允许"晚上提交作业、隔夜跑完"的运行方式,代价是吞吐率直接决定成本——吞吐被定义为任务整个运行时间(可达数小时)内每秒处理的 token 数。这种特性使得"用延迟换吞吐"成为可行策略,也让低成本的普通商用 GPU 有了用武之地。
1.2 三大关键技术
FlexGen 应对资源约束的三大手段(README "How It Works" 一节与论文摘要一致):
- 异构资源聚合(GPU + CPU + Disk):在不同硬件资源约束下灵活配置,把权重、激活、注意力 KV cache 分散存放在 GPU 显存、CPU 内存与磁盘上,按需加载计算;
- 线性规划(LP)策略优化器:通过线性规划自动搜索张量"存哪里、何时访问"的最优模式,在给定硬件(GPU/CPU/磁盘容量与带宽)约束下最大化吞吐;
- 4-bit 分组量化压缩:对权重与注意力 KV cache 均压缩到 4 bit,精度损失可忽略(negligible),从而把"可容纳的批大小"上限大幅抬升。
1.3 代表性结果(以论文/README 为准)
论文摘要给出了两个标志性结论,均基于 GCP 上单块 NVIDIA T4(16GB)实例、208GB DRAM、1.5TB SSD 的环境(input seq len=512,output seq len=32,批大小调至各系统最大吞吐值):
- 运行 OPT-175B 时,FlexGen首次在单 16GB GPU 上达到 1 token/s 的生成吞吐,有效批大小 144(配合压缩后的数字见下文性能表);
- 在 HELM 基准上,FlexGen 用 16GB GPU 在 21 小时内完成了 30B 模型在 7 个代表性子场景下的跑分。
二、上手实测:从 OPT-1.3B 到 OPT-175B
2.1 安装
仓库 README 给出两种安装方式,唯一硬性要求是PyTorch >= 1.12:
# 方式一:pip 安装 pip install flexgen # 方式二:源码安装 git clone https://github.com/FMInference/FlexGen.git cd FlexGen pip install -e .2.2 OPT-1.3B:无卸载快速体验
小模型可直接放进单 GPU,无需卸载。FlexGen 会自动从 Hugging Face 下载权重:
python3 -m flexgen.flex_opt --model facebook/opt-1.3b运行后会看到 OPT-1.3B 生成的文本以及 benchmark 结果(prefill/decode 延迟与吞吐,见 flex_opt.py 的日志逻辑)。
2.3 OPT-30B:引入 CPU 卸载与--percent
python3 -m flexgen.flex_opt --model facebook/opt-30b --percent 0 100 100 0 100 0--percent是 FlexGen 最核心的参数。它接收 6 个整数,依次表示(源码注释原文,见 flex_opt.py):
| 位置 | 含义 | 默认值 |
|---|---|---|
| 1 | 权重放在 GPU 的百分比 | 100 |
| 2 | 权重放在 CPU 的百分比 | 0 |
| 3 | 注意力 cache 放在 GPU 的百分比 | 100 |
| 4 | 注意力 cache 放在 CPU 的百分比 | 0 |
| 5 | 激活(activations)放在 GPU 的百分比 | 100 |
| 6 | 激活放在 CPU 的百分比 | 0 |
每一类的"磁盘百分比"是隐含的第三项,由Policy属性计算得出(flex_opt.py):
@property def w_disk_percent(self): # 权重磁盘占比 return 100 - self.w_gpu_percent - self.w_cpu_percent @property def cache_disk_percent(self): # cache 磁盘占比 return 100 - self.cache_gpu_percent - self.cache_cpu_percent @property def act_disk_percent(self): # 激活磁盘占比 return 100 - self.act_gpu_percent - self.act_cpu_percent实际分配时,init_weight_list会按张量体积的累计分布(cumsum)把不同权重切成三段,分别落到磁盘、CPU、GPU(flex_opt.py)。因此--percent 0 100 100 0 100 0的含义是:权重全部放 CPU、cache 与激活全部放 GPU——这是 30B 在 16GB 显卡上的典型起点。参考策略可见 benchmark/flexgen/bench_suite.py:30B 无压缩时通常采用--percent 20 80 0 100 0 100或--percent 10 90 0 100 0 100(约 10%~20% 权重驻留 GPU,其余在 CPU),并搭配--gpu-batch-size 48 --num-gpu-batches 3之类的分批参数。
2.4 OPT-175B:全量卸载到磁盘
OPT-175B 需要先从 metaseq 项目下载权重,并按 Alpa 格式转换,然后可将全部权重卸载到 SSD:
python3 -m flexgen.flex_opt --model facebook/opt-175b --percent 0 0 100 0 100 0 --offload-dir YOUR_SSD_FOLDER--offload-dir默认值为~/flexgen_offload_dir(flex_opt.py),用于存放卸载到磁盘的张量。
三、吞吐优先场景:HELM 基准与数据整理应用
3.1 将 FlexGen 接入 HELM
FlexGen 可以作为 HELM 的执行后端。README 给出的 MMLU 场景示例命令,可在单块 T4(16GB)+ 200GB DRAM 上运行:
pip install crfm-helm python3 -m flexgen.apps.helm_run --description mmlu:model=text,subject=abstract_algebra,data_augmentation=canonical --pad-to-seq-len 512 --model facebook/opt-30b --percent 20 80 0 100 0 100 --gpu-batch-size 48 --num-gpu-batches 3 --max-eval-instance 100实现侧,flexgen/apps/helm_run.py 中的execute会构造ExecutionEnv与Policy,将 HELM 请求按effective_bs分批:get_batches先用 tokenizer 把 prompt 填充到pad_to_seq_len,再按 batch_size 切分(helm_run.py)。README 提醒:仅测试了部分 HELM 场景,已测试场景清单见 flexgen/apps/helm_passed_30b.sh。
3.2 数据整理(Data Wrangling)任务
论文的姊妹工作《Can Foundation Models Wrangle Your Data?》中的示例可以直接复现,操作说明位于 flexgen/apps/data_wrangle。该目录下 data_wrangle_run.py 同时提供single_query_test与batch_query_test两种模式,分别对应单条查询与批量查询测试脚本(如 test_batch_query_all_opt30b.sh),正是吞吐优先场景的典型落地。
四、API 使用:Hugging Face 风格的生成接口
4.1 生成 API
FlexGen 提供仿 Hugging Face transformers 风格的生成 API,核心签名见 completion.py:
output_ids = model.generate( input_ids, do_sample=True, temperature=0.7, max_new_tokens=32, stop=stop)底层OptLM.generate支持debug_mode、cut_gen_len(截断生成长度用于快速调试)等参数,并内置 normal / overlap 两类生成循环(generation_loop_normal、generation_loop_overlap_single_batch、generation_loop_overlap_multi_batch等,见 flex_opt.py 中的方法定义)。
4.2 示例命令
- 完整 OPT-6.7B,至少 15GB 显存:
python3 -m flexgen.apps.completion --model facebook/opt-6.7b- 完整 OPT-30B,约需 90GB CPU 内存:
python3 -m flexgen.apps.completion --model facebook/opt-30b --percent 0 100 100 0 100 0- 指令微调的 OPT-IML-MAX-30B,同样约需 90GB CPU 内存:
python3 -m flexgen.apps.completion --model facebook/opt-iml-max-30b --percent 0 100 100 0 100 0注意completion.py内置了两个示例 prompt(奥运会地点问答、机场代码抽取),并在生成结束后调用env.close_copy_threads()关闭磁盘拷贝线程(completion.py)。
五、性能数据与复现方法
5.1 生成吞吐对比表
README "Performance Results" 中的对比表(括号内为有效批大小及其最低卸载层级;硬件为 GCP 上 T4 16GB + 208GB DRAM + 1.5TB SSD;workload 为 input=512 / output=32,批大小按各系统最大吞吐调优;吞吐定义为 生成 token 数 ÷(prompt 处理时间 + 生成时间)):
| 系统 | OPT-6.7B | OPT-30B | OPT-175B |
|---|---|---|---|
| Hugging Face Accelerate | 25.12 (2 on GPU) | 0.62 (8 on CPU) | 0.01 (2 on disk) |
| DeepSpeed ZeRO-Inference | 9.28 (16 on CPU) | 0.60 (4 on CPU) | 0.01 (1 on disk) |
| Petals | 8.25 (2 on GPU) | 2.84 (2 on GPU) | 0.08 (2 on GPU) |
| FlexGen | 25.26 (2 on GPU) | 7.32 (144 on CPU) | 0.69 (256 on disk) |
| FlexGen with Compression | 29.12(72 on GPU) | 8.38(512 on CPU) | 1.12(144 on CPU) |
对应的有效批大小表与 Petals 基线说明见 benchmark/batch_size_table.md。完整复现方法(含 1x1 / 1x4 / 4x1 等多种拓扑的 shell 脚本与 bench_suite.py 自动化套件)见 benchmark/flexgen/README.md。
从 bench_suite.py 可以直观看到压缩带来的批大小提升:30B 无压缩时--gpu-batch-size 48 --num-gpu-batches 3(有效批 144),而启用--compress-cache后达到--gpu-batch-size 64 --num-gpu-batches 8(有效批 512)——与 README 表中数字一一对应。175B 压缩配置则采用--percent 0 100 0 100 0 100 --compress-weight --compress-cache的"全 CPU"策略,配合--pin-weight 0以缓解内存压力。
5.2 延迟-吞吐权衡(Pareto 前沿)
README 中docs/throughput_vs_latency.jpg(查看图片)展示了三个基于卸载的系统在 OPT-175B(左)与 OPT-30B(右)上的延迟-吞吐曲线:FlexGen 达成新的 Pareto 最优前沿,最大吞吐显著更高,而其他系统因内存不足无法继续增大批大小;图中 "FlexGen(c)" 即启用压缩的 FlexGen。
六、工作原理:批调度、I/O 重叠与策略搜索
6.1 吞吐视角下的延迟-吞吐权衡
FlexGen 的关键洞见是主动利用延迟-吞吐权衡:卸载方案天生难以实现低延迟,但在吞吐优先场景下,卸载的 I/O 效率可以被大幅提升。具体手段是block schedule(块调度):按块复用权重、把 I/O 与计算重叠(overlap),而基线系统普遍采用低效的逐行(row-by-row)调度。README 用 docs/block_schedule.jpg 直观对比了两种调度方式(a 为基线逐行、b 为 FlexGen 块调度)。
这一思想在源码中落地为Policy的overlap字段(默认 True,见 flex_opt.py)以及OptLM的三套生成循环:generation_loop_overlap_single_batch与generation_loop_overlap_multi_batch专门负责在多 GPU batch 之间交错加载权重与计算,从而隐藏磁盘/CPU 加载延迟。benchmark 套件中常见--overlap False的对照实验(bench_suite.py),便于量化重叠带来的收益。
6.2 线性规划策略优化器与成本模型
论文所述"通过线性规划优化器搜索张量存储与访问的最优模式",对应仓库 experimental/cost_model.py。它基于pulp线性规划库实现,典型用法:
# 1. 在给定硬件约束下自动搜索最优策略 python cost_model.py --model facebook/opt-30b --prompt-len 512 --gen-len 32 \ --gpu-mem 16 --cpu-mem 200 --nvme-mem 1500 # 2. 估算给定策略的吞吐 python cost_model.py --model facebook/opt-30b --prompt-len 512 --gen-len 32 \ --gpu-mem 16 --cpu-mem 200 --nvme-mem 1500 \ --gpu-batch-size 48 --num-gpu-batches 3 \ --percent 20 80 0 100 0 100 \ --alpha-g 1.2 --alpha-c 1.2 --alpha-n 1.2文件头部注释明确给出了使用须知(cost_model.py):硬件常数(CostModelConfig)需要针对自己的设备重新拟合(作者通过采集真实运行数据点用梯度下降拟合,直接 profile 单个算子或从网络抄数都不准确);alpha_g/alpha_c/alpha_n是峰值内存估计的松弛系数,调小策略偏保守、调大偏激进;当前模型不考虑 CPU 计算委托,且量化支持不完整。README 的 Roadmap 也标注"Release the cost model and policy optimizer"为已完成项([X])。
6.3 4-bit 分组量化:权重与 KV cache 双压缩
压缩由 flexgen/compression.py 实现,核心是CompressionConfig(分组量化配置)与TorchCompressedDevice(压缩张量管理设备)。运行时通过两个开关开启:
--compress-weight # 压缩权重(约省 70% 权重内存) --compress-cache # 压缩 KV cache两者默认的分组量化配置(flex_opt.py)为:
- 权重:
CompressionConfig(num_bits=4, group_size=64, group_dim=0, symmetric=False) - cache:
CompressionConfig(num_bits=4, group_size=64, group_dim=2, symmetric=False)
从 compression.py 的实现可以看到压缩存储的具体形态:4-bit 数据按group_size=64分组,data张量按"每 2 个 4-bit 值打包成 1 个 uint8"的方式存放(data_shape = shape[:group_dim] + (num_groups * (group_size // 2),) + ...),并附带一个 fp16 的scale张量记录每组缩放因子。compress/decompress函数完成实际量化与反量化;cache 压缩时还会在 CPU 上分配 fp32 反量化工作区(init_attention_compute_workspace,见 compression.py)。README 提示,权重压缩大约可减少 70% 的权重内存,且论文报告压缩后精度损失可忽略(negligible)。
6.4 执行环境与内存层级抽象
FlexGen 把硬件抽象为统一的内存层级(utils.py 的ExecutionEnv+ pytorch_backend.py 中的TorchDevice/TorchDisk/TorchMixedDevice):
gpu = TorchDevice("cuda:0") cpu = TorchDevice("cpu") disk = TorchDisk(args.offload_dir) env = ExecutionEnv(gpu=gpu, cpu=cpu, disk=disk, mixed=TorchMixedDevice([gpu, cpu, disk]))权重按Policy的百分比切分后分别allocate在 disk/cpu/gpu 上(init_weight_list),推理时通过load_weight/load_cache/store_cache在层级间搬运,磁盘侧使用多线程拷贝(TorchDisk默认 4 个拷贝线程)隐藏 I/O 延迟。--pin-weight 0可关闭 CPU 端权重页锁定(pinned memory),约减少 20% 以上的 CPU 权重内存占用(README FAQ),代价是拷贝稍慢。
6.5 分布式扩展:卸载 + 流水线并行
当多机多卡但聚合显存仍小于模型大小时,FlexGen 可把卸载与流水线并行(pipeline parallelism)结合:DistOptLM(dist_flex_opt.py)继承OptLM,引入pipeline_rank/num_pipeline_stages/comm_device等参数,并通过send_hidden/recv_hidden在流水线阶段间传递激活。README 提示:要获得可扩展的性能,GPU 应分布在多台机器上(同机多卡性能优化仍在其 Roadmap 中列为未完成项)。分布式 benchmark 脚本见 benchmark/flexgen/bench_dist_single_node.sh 与 benchmark/flexgen/bench_dist_multi_node.sh。
七、FAQ:策略调参与内存不足排查
7.1 如何设置卸载策略(--percent)?
README 明确说明:目前需要手工尝试若干策略(自动策略优化器已随 cost model 发布,但调优仍需人工)。总体原则是:尽可能把参数与注意力 cache 卸载到 CPU、必要时到磁盘,从而把显存让给更大的批大小。可直接参考 bench_suite.py 中的基准参考策略。出现 OOM 时,把--percent中对应项调向 CPU/磁盘方向即可卸载更多张量。
7.2 内存不足(OOM)时怎么办?
README FAQ 给出三条由"省内存 → 更慢"排序的应急手段:
- 不锁定权重:加
--pin-weight 0,CPU 权重内存约省 20% 以上; - 压缩权重:加
--compress-weight,权重内存约省 70%; - 权重全部落盘:
--percent 0 0 100 0 100 0(配合--offload-dir),几乎不占 CPU 与 GPU 内存。
更进阶的排查可借助profile_bandwidth.py(flexgen/profile_bandwidth.py,测磁盘与 PCIe 带宽)与profile_matmul.py(flexgen/profile_matmul.py,测矩阵乘性能)先行刻画本机硬件常数,再用 cost_model.py 预估各策略的吞吐,减少盲目试参。
八、结语与路线图
FlexGen 证明了一条"弱硬件 + 极致 I/O 调度 + 压缩 + 大批量"的可行路径:在 16GB 单卡上首次达到 OPT-175B 的 1 token/s 生成吞吐,并把 HELM 30B 跑分压缩到 21 小时。它明确面向吞吐优先的批量场景,代价是小批量/低延迟场景不具优势。README Roadmap 显示其后续计划包括:优化同机多卡性能、支持更多模型(BLOOM、CodeGen、GLM)、Macbook(M1/M2)与 AMD 支持。论文全文出处为 docs/paper.md 所收录的 arXiv 论文《High-throughput Generative Inference of Large Language Models with a Single GPU》(arXiv:2303.06865,作者包括 Ying Sheng、Lianmin Zheng 等),Subj 分类为 cs.LG / cs.AI / cs.PF。
- 推理引擎
- 大模型
【免费下载链接】FlexGen
Running large language models on a single GPU for throughput-oriented scenarios.
相关推荐
推荐文章:FlexGen——单GPU下大型语言模型高吞吐量推理的新引擎
推荐文章:FlexGen——单GPU下大型语言模型高吞吐量推理的新引擎 在当今人工智能的快速发展中,大型语言模型(LLMs)正以前所未有的方式重塑我们对信息处理
推理引擎大模型FlexGen 单 GPU 高吞吐大语言模型推理引擎:从安装、Offloading 策略到 HELM 与数据整理实战
FlexGen 单 GPU 高吞吐大语言模型推理引擎:从安装、Offloading 策略到 HELM 与数据整理实战 FlexGen 是一个面向"吞吐优先(th
推理引擎大模型FlexGen 基准测试实战指南:单 GPU 与多机多卡 OPT 模型吞吐量测试全解析
FlexGen 基准测试实战指南:单 GPU 与多机多卡 OPT 模型吞吐量测试全解析 本篇技术指南围绕 FlexGen 官方基准测试方案( benchmark
推理引擎大模型
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考