☰
LMDeploy量化部署实战:从显存规划到LLM/VLM推理优化
2026/10/19 10:26:23 网站建设 项目流程

最近在整理大模型部署的实战流程,终于轮到写这一篇了:LMDeploy 量化部署 LLM-VLM 实践。之前几次分享都是从零跑通推理,但真正到了上卡、上服务的阶段,光能跑不够,还得算显存、控成本、压延迟。LMDeploy 这个开源部署工具包,是我目前用过最顺手的量化部署方案之一,尤其适合同时管 LLM 和 VLM 两类模型。这篇文章会从量化原理讲到完整实操,再到我踩过的几个坑,尽量把每个决策背后的为什么也说清楚,不是简单甩几条命令。

如果你正准备把开源大模型落地到单卡或内部服务,或者手里只有消费级显卡却想跑 7B、13B 级别的模型,这篇文章适合你。我会按一套可复现的流程来写,让你看完能直接照做。

1. 为什么量化部署不是“锦上添花”,而是刚需

1.1 一张卡能装下什么模型,是部署的第一道坎

很多初学者第一次跑大模型,先被卡死在显存上。拿一个 7B 参数级别的底座模型来说,如果直接加载 FP16 权重,就是 7 乘以 2 个字节,约等于 14GB 显存。这还只是权重本身,没算激活值、KV Cache、CUDA 上下文、视觉编码器这类额外开销。也就是说,一张 16GB 显存的卡,理论上能塞进 7B 模型,但实际跑起来稍长一点的对话就会触顶。13B 模型更夸张,FP16 光权重就 26GB,想单卡跑基本是做梦。

我最初做部署实验时,也想过“反正显存不够就买更大的卡”,但现实的约束往往是:手头只有一两张 24GB 的卡,内网服务器调度也不一定让你独占整机。这时候量化就是最直接的答案。把权重压到 4bit,7B 模型的权重能从 14GB 降到 3.5GB 左右,加上其余开销,一张 24GB 的卡不仅能放下,还能留出空间给比较大的并发批次。

量化不是可有可无的优化,它是把模型部署到“普通硬件”上的关键手段。很多人觉得量化是牺牲精度换显存,这个说法太笼统。以现在主流的 4bit 权重量化方案,配合适量校准数据,大多数任务上的损失已经控制在可接受范围内,尤其是生成类任务,体感上不会像你想的那样掉一截。

1.2 量化到底在压哪几块:权重、激活和 KV Cache

量化这个词听起来玄乎,本质就是把原来用 16bit 浮点表示的数值,换成更低比特的整数来表示。越小的比特数,每个数占的字节越少,显存占用自然降下来。但这里有个容易忽略的点:不是所有东西都必须量化。

第一块是权重。这是占显存的大头,也是量化收益最高的地方。常见的方案是只把权重从 FP16 压到 INT4,激活值仍然保持 FP16,这种组合有个专门叫法,W4A16。意思是 Weight 4bit,Activation 16bit。为什么不全量化成 4bit?因为激活值的分布动态很大,量化它容易损失精度,而且对推理速度的贡献不像权重那么直接。W4A16 是目前部署场景里性价比很高的折中。

第二块是 KV Cache。这是 LLM 生成过程中的关键中间产物,每生成一个 token,都要把历史的 Key-Vector 和 Value-Vector 缓存下来。序列越长,KV Cache 越大。尤其是在长文本对话或者批量处理时,KV Cache 能分走大量显存。LMDeploy 支持把 KV Cache 也做 INT8 或 INT4 量化,能在不显著影响生成质量的前提下,把这块开销压下去。实际操作中,KV Cache 量化往往比权重量化更“救急”,因为很多 OOM 都是生成到一半爆掉的。

第三块是视觉编码器。VLM 和 LLM 的区别在于它多了一个视觉编码器,用来把图片转成视觉 token。这块通常不大,一个中等规模的视觉编码器也就零点几 B 到 1B 参数,但浮点计算密集。我的经验是,视觉编码器一般保持原精度不量化,因为多模态模型的视觉特征对量化误差更敏感,量化收益也不大。

1.3 为什么选 LMDeploy,而不是自己写量化管线

理论上你可以用通用框架加载 4bit 模型,但这里有个隐藏的坑:把权重量化成 4bit 之后,GPU 上真正高效的矩阵运算需要特殊的 kernel 支持。如果你只是硬塞进一个普通推理框架,计算时可能还要先反量化回 FP16,速度反而变慢,甚至内存占用也没省多少。

LMDeploy 这类工具包的价值就在这:它内置了专门为量化模型优化的推理后端,对 W4A16、KV Cache 量化这些场景做了计算层适配,让“省显存”和“跑得快”同时成立。再加上它自带服务化能力,能直接起一个兼容常见接口的 API 服务,省了我另外搭一层的东西。

我选择它的另一个原因是操作直接。整条链路从模型转换、权重量化到启动服务,都能用它自带命令完成,不像自己写脚本那样要处理一堆张量切分、分组量化逻辑。当然,自己写量化代码能学到的细节更多,但对于目标是快速落地的人来说,用一个成熟工具有它的正当理由。

2. 部署前的准备:模型选型与显存规划

2.1 先分清你要部署的是 LLM 还是 VLM

LLM 和 VLM 虽然都叫大模型,但部署负载的画像不太一样。纯文本 LLM 的负载主要由权重和 KV Cache 构成,比较容易被量化方案覆盖。VLM 则多了一条视觉链路:输入图片先经过视觉编码器,变成视觉 token,再拼到文本序列里一起进语言模型。这意味着 VLM 的显存占用是两部分叠加,而且图片分辨率越高、视觉 token 越多,KV Cache 的增长就越明显。

所以部署前不要急着执行命令,先想清楚使用场景。如果只是做纯文本对话,那可以完全按 LLM 流程来,量化和 KV Cache 优化都放开。如果要处理图片输入,就要额外关注视觉编码器的输入预处理、图片 token 长度上限、以及多图场景下 KV Cache 的倍增效应。

我建议在一开始就把模型类型明确写进部署文档里,别等到启动服务后才想起来。比如同样是量化命令,LLM 和 VLM 在转换时指定的输入结构、预处理配置都不完全一样,混着用会出现“模型能加载,但一喂图片就报错”的情况。

2.2 显存预估:一张表算清你的卡够不够

动手之前,先用一个简单公式做粗算。权重显存大约等于参数量乘以每参数字节数。FP16 是 2 字节,INT8 是 1 字节,INT4 是 0.5 字节。7B 模型的 FP16 权重约 14GB,INT4 约 3.5GB;13B 模型则分别约 26GB 和 6.5GB。再加上激活值、KV Cache、框架开销,如果做 W4A16 量化,7B 模型放在 24GB 显卡上,余量是比较充足的;13B 模型放 24GB 也基本可行,但要把 KV Cache 量化打开,同时控制一下并发数。

模型规模FP16 权重INT4 权重(W4A16)常见显卡建议
7B~14GB~3.5GB24GB 卡可流畅部署并可开并发
13B~26GB~6.5GB24GB 卡需配合 KV Cache 量化
视觉编码器(VLM 场景)约 0.5GB - 1GB一般不量化单独计入显存

这里说的都是权重维度,实际服务时还需要给 KV Cache 留出“缓冲区”。我习惯的做法是,先按最大输出的 token 数估算 KV Cache 上限,然后再决定并行 batch 是多少。比如一个 7B 模型,如果单条输出 2048 token 就占了比较多 KV Cache,那么并发 4 条请求就需要同步放大 4 倍估算。宁可预估得保守一些,也别等到线上跑满了再调。

2.3 环境要求与依赖版本问题

LMDeploy 的安装本身不算复杂,通过 Python 包管理器安装即可。但有几个环境层面的坑值得提前说。第一是 CUDA 版本,太老或太新的 cuBLAS 版本都可能导致量化 kernel 跑不起来。我踩过最典型的一次是加载成功后,一推理就报底层 CUDA 错误,最后发现是 CUDA 运行时与当前驱动不匹配。第二是 Python 版本,太旧的版本可能装不上较新的依赖包。第三是模型缓存目录的磁盘空间,量化过程会生成中间产物,如果磁盘不够,会在转换阶段卡很久然后报错。

软件的版本稳定性也很关键。LMDeploy 迭代速度不算慢,不同小版本之间命令行参数有细微差别。我的建议是首次使用就把版本固定下来,部署文档里写清 Python 版本、CUDA 版本、LMDeploy 版本、模型缓存路径,这样换机器复现时才不会玄学报错。实测下来,锁定依赖版本能省掉非常多排查时间。

3. 实操:从原始模型到量化服务的完整链路

3.1 第一步:先拿原始模型做一次 baseline

量化之前,务必先把原始 FP16 模型跑通一次。这一步不是为了验证模型有没有问题,而是为了拿到“对照基线”。你只有知道原始模型在特定任务上生成的内容是什么质量,量化后做对比才有依据。否则一旦量化后出现输出变差,你很难判断是量化造成的,还是本来模型就是这个水平。

实际操作时,我会先准备几个标准问题,包括一段文本续写、一道数学题、一个简单代码需求。如果是 VLM,再准备几张风格差异较大的图片,分别让原始模型描述物体、读取文字、做简单推理。把输出保存下来,标注好是第几次实验、用了什么参数。

baseline 这一步看起来很朴素,但至关重要。我见过不止一次,有人量化完说“模型变笨了”,结果一对比原始模型,发现原来它的 baseline 也不高。做量化前后对比时,最好用相同的解码参数,比如相同的采样温度和最大 token 数,这样才能排除解码策略差异的干扰。

3.2 第二步:使用 AWQ 方法做 W4A16 权重量化

LMDeploy 的量化流程里,权重部分我带大家走 AWQ(Activation-aware Weight Quantization)这条路。AWQ 的核心思路是,量化时不是对所有权重一视同仁,而是根据激活值的统计信息,给重要的权重通道更高的保护。听起来有点复杂,但实际使用中你只需要理解一个点:它需要一小部分校准数据,用来观察激活分布,然后决定量化误差怎么分配。

如果你跳过了校准数据这一步,随便给一个命令就开始量化,得到的模型也能跑,但精度往往不如用了合适校准数据的版本。校准数据不需要很多,几十到几百条有代表性的样本就够。我通常从真实场景里抽一部分用户问题或业务文本,混合成一个小文件做校准。对于 VLM,校准数据里最好带上图文样本,不要只给纯文本。

命令执行上,大致会经过两个阶段。先做 AWQ 量化搜索,得到量化后的权重格式;然后把量化结果转换成部署服务能直接加载的目录结构。整个过程中,显存和 CPU 内存都会有一定消耗,如果碰到 OOM,可以先缩小校准数据长度或减少 batch size。量化结束后,建议检查输出目录里是否有完整的配置文件,不要只看权重文件生成完就以为结束了。

3.3 第三步:KV Cache 量化与启动服务

权重量化解决的是“模型能不能装进卡里”的问题,KV Cache 量化解决的是“跑长文本时会不会中途 OOM”的问题。两者可以同时开启。LMDeploy 的服务启动参数里,会有与 KV Cache 量化相关的开关,一般可以直接设置成 8bit 或 4bit 模式。第一次尝试时从 8bit 开始,观察量化后生成质量,如果无明显退化,再考虑更低的 4bit。

启动服务时,我常用的方式是起一个兼容 OpenAI 接口的 API 服务,这样下游调用方不用关心模型是怎么部署的,直接按标准接口格式发请求就行。启动之后,先别急着接业务,先用 curl 或一个简单的 Python 脚本发几个测试请求,确认返回结构和预期一致。

一个小提醒:服务启动参数里的并发上限和 batch 大小要一起调。有些人只调并发数,不调 batch,导致显存被大量激活值占满。实际上,部署调优是一个组合参数问题,不能单点看一个值。我一般会把显存占用和延迟一起记录,调完一组参数再改下一组,避免凭感觉乱试。

3.4 VLM 部署差异点和多图场景配置

VLM 的推理链路比 LLM 多了一段视觉处理。部署时首先要确保视觉编码器对应的图像预处理配置能被加载,比如图片缩放到什么尺寸、是否需要 padding、token 长度的上限是多少。图片分辨率如果太高,视觉 token 数量会暴增,KV Cache 随之膨胀。因此,如果业务场景不需要超高分辨率,我会在预处理里限制输入尺寸,这样既能减少显存,也能加快速度。

多图场景是另一个容易忽略的地方。当你一次对话里传入多张图片时,视觉 token 是逐张累加的,KV Cache 增长会更剧烈。代码层可能支持多图,但硬件层未必扛得住。我的建议是,在多图模式下把最大输出长度、batch size 都适当调小,或者先跑一个小压力脚本,看看多传几张图后显存峰值到多少,再决定能不能放开。

VLM 量化还有个实操注意点:视觉编码器部分通常不做低比特量化。原因是图片特征被压到 4bit 后,模型对细节内容的感知明显变钝,OCR、图像描述这类任务掉点最明显。所以典型的部署策略是:语言模型主干走 W4A16 量化,视觉编码器保持高精度,KV Cache 选择性量化。这样既省了主要显存,又保住了多模态核心能力。

4. 实测:三个纬度判断配置是否合理

4.1 显存占用:先看峰值,再看稳态

部署完成后,我第一个观察的指标是显存峰值。启动服务瞬间会有一次比较大的显存申请,这不代表真实负载,要等模型加载完、跑几个请求后再看稳态占用。我会监控显存曲线,如果峰值出现在最长的生成请求末尾,说明 KV Cache 可能是瓶颈;如果峰值出现在请求刚进来时,说明激活值或 batch 设置需要调整。

单靠任务管理器里的显存数字还不够精细,我会额外在服务日志里打开显存统计,或者用底层监控工具记录一段时间。量化后 7B 模型通常能腾出一大半显存,这些余量可以用于提升并发或加长输入输出。但注意,别把显存用得太满,量化 kernel 在显存紧张时容易出现莫名报错,留 1GB 到 2GB 缓冲区是经验值。

4.2 延迟和吞吐:首 token 延迟比总延迟更关键

在线交互场景里,用户最直观的感受是首 token 延迟,也就是发送请求后到第一个 token 返回的时间。量化模型因为计算路径更短,首 token 延迟往往不错。如果首 token 延迟很高,问题多半出在输入预处理、模型加载方式或视觉编码环节,而不是生成环节。

吞吐则看每秒能生成多少 token。这里要提醒一个常见误区:单看总耗时没意义,因为总耗时跟输出长度强相关。我习惯用“生成阶段每秒 token 数”来评估模型速度,同时记录并发请求下的吞吐变化。量化后如果发现单请求速度下降,但并发吞吐明显提升,这通常是划算的,因为整体服务能力上去了。

4.3 精度损失的主观评估与客观回退条件

精度评估要分场景。像数学题、代码生成这类对数值敏感的任务,量化损失会被放大。我一般会做两类评估:一类是自动化评测集,跑一批标准化问题,统计正确率;另一类是主观体验,连续做几十轮对话,看有没有答非所问、逻辑断裂、图片细节丢失等情况。

如果评测结果相比 FP16 基线有明显变差,我建议回退到损失更小的方案。优先级大概是:先确认是不是校准数据不合适,再尝试 KV Cache 从更低比特回到 8bit,最后才考虑放弃权重量化。不要一看到掉点就直接放弃量化,很多时候只是某个环节没做对。

5. 常见问题与排查实录

5.1 量化模型加载时直接报错

这一类问题大概率不是模型文件损坏,而是格式不匹配。最常见的原因是,模型原始格式和量化后生成格式混在一起,服务端不知道以哪种方式解析。解决办法是严格按照流程走:先在独立目录完成 AWQ 量化,再把转换产物放到统一目录,不要手动修改目录名字或混放文件。

如果报错信息指向算子不支持,先检查 CUDA 和 GPU 架构是否太老。Pascal 之前的架构对很多量化 kernel 支持很差,基本不用考虑跑 4bit 推理。另外,把依赖版本统一是很有效的排查动作,我在锁定版本后再没遇到过这类问题。

5.2 量化后输出质量明显变差

先别急着骂量化,先检查校准数据。AWQ 对校准数据敏感,如果你用的是随机乱码文本或无意义内容,量化出来的模型几乎必然掉点。正确做法是准备一批和业务分布一致的样本,条数不用多,覆盖类型要广。如果校准数据没问题,再看量化粒度,group size 越小,量化误差通常越小,但显存节省会略打折扣,需要在这两者间做折中。

还有一个我踩过的场景:量化时没有设置随机种子,每次执行结果不完全一致。虽然模型还能用,但对比实验就会变得没有说服力。所以量化时固定随机种子,让过程可复现。

5.3 VLM 图片输入报错或输出空洞

图片输入报错大多是预处理配置和模型不匹配。不同 VLM 对图片尺寸、归一化方式的要求不同,如果换了模型只改权重路径,很容易出现“文本能答、图片直接崩”的情况。我的排查顺序是:先确认图片有没有成功被预处理成预期张量,再确认视觉 token 有没有拼进对话序列。

如果图片没报错但输出空洞,多为视觉编码器精度被误伤,或图片 token 数量被截断得太狠。检查一下输入分辨率限制,并把视觉编码器保持高精度重启服务试试。

5.4 并发一高就 OOM

并发 OOM 基本都是 KV Cache 超预算。不要只看单请求的显存占用,要按并发数乘一下。解决办法:降低最大 batch、减少单请求最大输出长度、打开 KV Cache 量化。还有一个容易被忽略的点是,有些请求会输入超长上下文,服务端默认没有限制长度,导致 KV Cache 无限增长。我建议在服务层设置最大上下文长度,一旦超长就拒绝或截断,而不是让显存跟着被打爆。

以下是一个简要的问题速查表,方便你现场对照:

现象最可能原因排查/解决动作
启动即报错格式目录混用、依赖版本不一致重建干净目录并锁定版本
输出质量掉点校准数据不合适、量化粒度不合理换业务分布数据,调整 group size
VLM 图片报错预处理配置不匹配检查图片预处理和视觉 token 拼接
并发后 OOMKV Cache 超预算限制 batch、控制上下文长度、开 KV Cache 量化

6. 量化部署中容易忽略的三件小事

第一件小事先说校准数据的“业务纯度”。我之前有一轮量化,为了图省事直接拿了通用语料做校准,跑通用闲聊还行,一到专业问答就明显变虚。换上真实业务问题后,效果立刻回来了。所以校准数据不要偷懒,宁可少一点,也要贴近真实使用场景。

第二件小事是温度和解码参数的统一。量化本身只改变权重表示,不改变解码逻辑。但如果你在对比实验里用了不同解码参数,很容易把差异误判成量化导致的。我后来养成一个习惯:所有对比实验都单独保存解码参数快照,量化前后保持一致。

第三件小事是服务启动后的稳定性压测。不要只在单请求下验证,要模拟多个请求同时进来,让服务跑一段时间,观察显存和延迟曲线是否平稳。很多问题在短时间单次请求里根本暴露不出来,只有在持续负载下才会现出原形。做完这几步,LMDeploy 量化部署 LLM-VLM 的整条链路基本就稳了,后续遇到新模型也能沿着这套方法论快速复现。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询