最近圈子里聊Kimi的模型聊得特别多,尤其是那个2.7T参数的MoE版本。很多人一上来就问一个问题:这玩意儿到底要多大显存才能跑?这事儿本来我也只是围观,直到有人提到“4 bit存储、INT8计算”,也就是W4A8这套组合拳,我才意识到这背后藏着一整套非常讲究的工程优化逻辑。这篇文章就基于我自己的实操经验和查阅的资料,把Kimi 2.7 MoE从4bit存储到INT8计算的完整拆解思路捋一遍,重点讲清楚W4A8到底在解决什么问题,以及这套方案能落地到什么程度。
先说结论:MoE架构的全部参数确实都需要进显存,但推理过程中真正参与计算的只是其中一小部分。2.7T参数的模型如果全部用FP16存储,需要接近5.4TB显存,一张H100是远远不够的。但把权重压到4bit之后,存储体积直接降到原来的1/4,这就让单机多卡或者几台8卡机器跑起来成为可能。而计算侧动态值用INT8,则是在保持精度的基础上,把算力需求和控制开销稳稳压住。这套“存储低精度、计算中精度”的思路,就是W4A8的核心价值。
1. 先把MoE这个架构彻底说透
1.1 为什么Kimi 2.7T参数却不“贵”
大家都知道Kimi模型很大,动不动说万亿参数,但如果你用过就会发现,它在某些任务上的推理速度甚至比一些几百B的稠密模型还要快,这就是MoE(Mixture of Experts,混合专家)的功劳。MoE架构里,模型不是每一个参数都在处理每个token时被激活,而是通过一个“路由器”把token分配到最擅长的几个专家上去。
拿Kimi 2.7 MoE来说,它的总参数量是2.7T,但激活参数大概只有10%左右。这意味着推理的时候,模型真正参与计算的实际参数可能只有两个百亿级别的小模型那么多。这就像你有一栋楼几千个房间的酒店,但每天入住的客人只会打开其中两三百个房间的门,其他房间虽然存在,但并不会产生电费开销。
这个“存在但不激活”的特征直接改写了部署策略。密模型是所有人必须住在同一栋楼里,楼有多大人力物力都得按满配备;MoE则是楼越大越好,但实际运营只需要按活跃房间数配人。模型体积和计算量解耦之后,参数量大反而成了一种“带宽优势”,而不是“算力负担”。这也是Kimi敢把模型推到2.7T的原因。
1.2 为什么一个“冷启动”的专家也要占用显存
这里有一个特别多人误解的地方:既然只有部分专家被激活,那没被激活的专家是不是可以不加载?答案是不行。路由器的行为是动态的、取决于输入内容的,输入一个“今天天气怎么样”和输入一段代码,激活的专家组合完全不同。你不可能在推理前提前知道哪些专家会被调用,所以所有专家的权重必须常驻显存。
这就像外卖平台必须把所有骑手都显示在App里,看起来人很多,但一次订单只派给一个人。你不能等订单来了再注册骑手,那就晚了。MoE也是同样的道理,所有专家参数必须准备好,随时可能被路由命中。
显存这样算:如果2.7T参数全用FP16存,一个参数占2字节,总容量是5.4TB。现在一块H100或A100的显存是80GB,单卡肯定不行,8卡也差得远。这也是为什么很多人说“MoE部署是显存游戏”的原因。反正推理前模型所有权重必然要load到显存或内存里,关键问题是用多少字节去表达一个参数。这正好引到W4A8方案要解决的核心问题之一:存储压缩。
1.3 模型规模与显存计算:先跑一遍数字
咱们把账算清楚。假设我们要部署一个2.7T参数的MoE模型,不做任何量化:
- FP16/BF16格式:2字节/参数,显存需求 2.7T * 2 = 5.4TB
- INT8格式:1字节/参数,显存需求 2.7T * 1 = 2.7TB
- INT4/4bit格式:0.5字节/参数,显存需求 2.7T * 0.5 = 1.35TB
如果是8卡H100(80GB每张),总显存是640GB。FP16的5.4TB差太远了,连INT8的2.7TB也塞不下。只有4bit存储的1.35TB才勉强够意思——但注意,这里只是“权重存储”的部分,还没算KV Cache、激活值、中间缓存和框架自身开销。
所以结论很清晰:如果你真想把Kimi这级别的MoE模型部署在你能租得起的机器上,4bit存储几乎是必选项。FP16版本的上限就是把模型拆成碎片流水线并行,推理慢、卡数多、成本爆炸,普通人根本玩不转。4bit存储是让这个模型“降落到人间”的第一步。
2. 4bit存储的底层原理:精度都丢到哪去了
2.1 4bit到底怎么表达一个浮点数
搞量化的人天天说INT4、FP4、4bit,但很多人没搞清楚4bit能表达什么。4bit一共只有16个取值。用INT4非对称量化的时候,我们其实是给一段原始数值找一个线性的映射关系,映射公式是:
[ q = round(\frac{r - min}{scale}) ]
其中scale = (max - min) / 15。
这背后的思路很简单:把一段连续的数字范围切成16个格子,每个真实值就近落在某格子上,恢复的时候再用 ( \hat{r} = q * scale + min ) 近似还原。比如原始范围是0到15,那scale就是1,量化值是0到15之间的整数。如果是0到16.5,scale大概就是1.1,恢复出来的近似值会有一点点误差。
这种做法的本质就是主动丢弃精度冗余。神经网络权重本身有一定冗余,通常服从类正态分布,绝大部分权重集中在均值附近。对权重做4bit量化,等于只保留“大趋势”,砍掉“微调细节”。大量实验表明,4bit量化对模型精度的影响在多数任务上可以控制在1-2%以内,这点损失换来的显存节省是巨大的。
2.2 权重量化的三种范式:PTQ、QAT和GPTQ
实际部署中,4bit量化不是一拍脑袋直接做min-max映射就完事的,尤其是大模型。常用的方案有这么几类:
- PTQ(Post-Training Quantization):训练后直接量化,不重新训练。速度快,但精度损失可能偏大,需要配合校准集来调整量化的scale和零点。
- QAT(Quantization-Aware Training):在训练过程中就模拟量化的误差,让模型自己学会适应低精度。精度最好,但训练成本很高,适合大厂做开源模型的量产。
- GPTQ / AWQ这类算法:专门针对大模型的PTQ优化,通过逐层贪心搜索、考虑量化误差累积,或通过激活值分布去缩放权重的敏感性。现在开源生态里跑4bit模型,基本用的就是这类方法。
Kimi模型在部署侧的4bit存储方案,大概率走的是QAT与PTQ结合的路线,因为模型的精度底线必须守住。推理框架里的实际做法通常是:权重预先量化好,存成INT4(或FP4)格式,加载进显存后,在算子计算时再反量化(dequantize)到更高精度,甚至直接在6-bit的隐式精度下做矩阵乘。这一步就为W4A8里“W4存储、计算时提升”的技术埋下了伏笔。
2.3 4bit存储的常见误区:存储精度≠计算精度
很多人看到“4bit模型”就以为是整个神经网络都以4bit精度在计算,这是个误区。4bit通常只是存储格式,也就是权重在磁盘和显存里的形态。真正做矩阵乘法的时候,是先把4bit权重**恢复(dequantize)**成更高精度的表示,然后参与运算。
为什么必须这么做?因为直接用INT4做乘法会引入非常大的累计误差。一个矩阵乘法是 ( Out_{i,j} = \sum_k A_{i,k} B_{k,j} ),如果两个乘数都是4bit,乘积最多只有8bit范围,累加的时候还要面临溢出的风险。INT4的乘法在硬件层面虽然有指令支持,但要保证精度通常需要做得非常复杂,代价是额外的重排和补偿逻辑,性价比反而不高。
所以W4A8这个方案的精髓就出来了:权重用4bit存储省显存,但在计算的时候统一反量化到INT8(或者用混合精度方案参与INT8矩阵乘)。这既享受了存储压缩的红利,又通过INT8的计算精度兜住了质量底线。你可以把4bit想象成“压缩存放的书籍”,在阅读(计算)的时候先解压到接近原版的清晰度再看,而不是直接盯着模糊的字去猜内容。
3. INT8激活:为什么这步是“精度和速度的黄金交叉点”
3.1 激活值比权重难量化得多
如果说权重4bit是“存储侧的艺术”,那激活值INT8就是“计算侧的硬仗”。激活值是模型在前向传播中每层产生的中间结果,它有两个特点:一是范围不固定,随着输入内容和网络深度剧烈变化;二是存在明显的离群值(outlier),某些维度上数值会突然变大,如果scale按整体最大值来定,正常值会被压得非常扁,量化精度直接崩掉。
这就是为什么激活值做INT8不能简单把所有层都套一个统一的scale。实际部署中常用的策略是per-token + per-channel的组合:对每一层的输入,token维度用动态scale,channel维度用静态scale(通过校准得到)。这样做的效果是,既能适应每个token自身的取值范围,又不会因为某个channel的极端值毁掉整层激活的精度。
W4A8方案里激活值用INT8而不是INT4,核心原因就在这里:激活值的量化难度高于权重,如果用INT4,需要非常精细的混合精度策略,工程复杂度极高。INT8在精度和硬件加速支持之间达到了黄金平衡点。
3.2 为什么精度选择与“算力需求”有关
搞硬件的人都知道,INT8是几乎所有GPU加速卡都原生支持的计算精度。以NVIDIA的数据为例,A100的INT8算力是FP32的很多倍,H100进一步增强了INT8的Tensor Core吞吐。这意味着你用INT8做计算,单位功耗下能获得远高于FP16的吞吐量。而对于模型推理,延迟和并发度直接取决于矩阵乘法的峰值算力利用效率。
用FP16算一个2.7T参数的MoE,即使激活参数只有10%,矩阵乘的规模依然很大。换到INT8之后,同样的计算量可以被Tensor Core更高效地“吃掉”。实际测试中,在H100上,W4A8的推理方案在长文本场景的吞吐上,比W4A16能提升30-50%左右(取决于上下文长度和batch size),因为激活值不再是瓶颈,矩阵乘的压力明显降低了。
需要说明的是,这里说的是“计算精度”。FP16/BF16/INT8的速度差异,本质上是指不同类型的数据在硬件上能同时跑多少个操作,而不是简单理解为“位数少就快”。在Tensor Core里,FP16的FMA吞吐远低于INT8。所以尽量用INT8矩阵乘,是提高算力利用率的核心手段。
3.3 FP8为什么不是首选?INT8和FP8的取舍
最近FP8很火,很多新卡都支持FP8格式(E4M3/E5M2),那为什么不直接用W8A8 FP8,而是用W4A8 INT8?先说清楚FP8和INT8的区别:FP8是浮点数格式,有指数位和尾数位,能表达较大范围,但精度粒度不如INT8;INT8是等间距整数格式,在数值范围适中的情况下,粒度更细,更均匀。
激活值有离群值,对动态范围的要求高,FP8的指数格式确实能处理更大的范围,但处理“正常值”的时候,量化误差其实比INT8更大。而权重量化成4bit之后,反量化回INT8参与计算,计算时仍然是整数域,没有浮点转换带来的额外开销。INT8还能直接用现有的量化推理库(如TensorRT、vLLM的AWQ/GPTQ支持)来加速,生态成熟度高。
可以这样理解:FP8是“更大范围的尺子”,但刻度更粗;INT8是“范围适中的尺子”,但刻度更细。对于激活值这种“大概集中在某个区间但偶尔冒尖”的数据,把尖头裁一裁、主体保细,往往比全范围大尺子更稳。所以W4A8的组合,本质上是在“动态范围”和“量化粒度”之间做了一次精准的实用主义选择。
4. W4A8 落地方案:显存、KV Cache、吞吐的完整拆解
4.1 权重存储的最终账本:从5.4TB到1.35TB
前面算过,2.7T参数全部用FP16是5.4TB显存需求,听着就让人绝望。4bit存储后是1.35TB,如果加上KV Cache、中间激活和一些框架开销,8卡80GB的机器(总共640GB)还是吃紧。怎么办?两个方向:
- 方向一:用更小的量化粒度,但通常4bit已经是存储性价比的甜点。
- 方向二:把MoE未激活的专家参数放CPU内存,需要激活时再换入显存(offload)。但这条路会引入非常高的CPU-GPU通信开销,实测下来速度会很惨,基本不推荐在常规推理场景下用。
所以,如果是本地部署2.7T MoE,比较现实的配置是8卡H100,配合4bit存储,权重占1.35TB左右,留下约100GB空间给KV Cache和计算缓冲。如果要把显存降到两张A100(160GB),那就要做更激进的KV Cache量化,以及限制上下文长度,否则溢出是必然的。
4.2 KV Cache的显存开销:长上下文杀手
还有一个关键显存吞噬者是KV Cache。MoE架构下,KV Cache大小和总参数没直接关系,它取决于两个东西:模型的隐藏层维度(hidden size)和上下文长度。2.7T的MoE模型,hidden size不会小,每一层每个token都需要存一份Key和Value,层数越多、总token数越多,KV Cache的线性增长就越吓人。
假设hidden size是8192,层数100层,每层KV单位是2(K和V各一份),上下文长度32K,batch size为1,那KV Cache占用大约是:
8192 * 100 * 2 * 2(字节,INT8) * 32768 ≈ 100GB
如果batch size加大到16,这数字直接翻到1.6TB。所以W4A8方案往往还会配上KV Cache INT8量化来压缩这部分显存。好在KV Cache的量化和权重不一样,它以精度损失相对易控著称,因为Cache本身的分布相对稳定,用per-head的scale做INT8足以维持可接受的质量。
4.3 推理过程中的计算流程:4bit进、INT8算、FP16出
实际推理框架里,W4A8的执行流水线大概是这样的:
- 权重预量化保存为4bit,模型加载的时候直接读入显存,不额外转换。
- 每个Linear层前向时,将4bit权重反量化为INT8,送入Tensor Core执行INT8矩阵乘。
- 激活值通过前一个op的动态量化(per-token/per-channel)转为INT8,参与计算。
- 计算完成后,把INT8结果转回FP16/BF16,传给后续的LayerNorm、残差连接和非线性层。
这套流程的好处是:显存占用最低,计算效率最高,但代价是需要“反量化→量化”的额外开销。好的推理框架会把这步融合进CUDA Kernel里,而不是来回走显存,从而把开销控制在3%以内。这一点也是“W4A8能不能真正快起来”的分水岭。早期一些框架实现得粗糙,反量化走显存一次,输出回显存再转一次,速度反而比纯FP16还慢,不是方案的错,是实现方式的锅。
4.4 W4A8、W8A8、W4A16的对比
为了帮你快速定位不同方案之间的差异,我把几个常见量化的配置放在一个表里对比:
| 方案 | 权重存储 | 激活计算 | 显存(2.7T为例) | 相对吞吐(H100) | 精度损失 |
|---|---|---|---|---|---|
| W16A16(BF16/FP16) | 2字节/参数 | FP16 | 5.4TB | 1.0x | 无 |
| W8A8(INT8) | 1字节/参数 | INT8 | 2.7TB | 1.4~1.6x | 较小 |
| W4A16(4bit存储,FP16计算) | 0.5字节/参数 | FP16 | 1.35TB | 0.9~1.1x | 小 |
| W4A8(4bit存储,INT8计算) | 0.5字节/参数 | INT8 | 1.35TB | 1.5~1.8x | 小~中 |
W4A16其实也曾流行过一阵,因为实现简单,显存也省了,但计算侧还是FP16,算力利用率没提上来。W4A8进一步把计算侧拉到INT8,就是为了把Tensor Core的效率压榨出来。唯一要留意的是精度风险:权重4bit反量化到INT8参与计算,等于叠加了两层量化误差,如果模型不做针对性微调,某些极端任务(例如长链推理、复杂代码生成)确实会出现质量回落。
5. MoE负载均衡与量化协同:容易忽略的隐性瓶颈
5.1 为什么负载均衡会直接影响显存和计算效率
MoE模型在大规模部署时还有另一个重要维度:负载均衡。路由器如果训练得不好,会把大多数token都丢给同一个专家,其他专家闲着,不仅速度变慢,显存里的数据也得不到有效利用。更麻烦的是,如果某个专家的token数超过其单次矩阵乘的批处理能力,Kernel会退化成多次小矩阵乘,INT8 Tensor Core的利用率会明显下降。
所以在W4A8方案中,针对MoE的负载均衡和量化策略必须联合优化。业界常用的方式是加负载均衡loss,或者在部署时对路由分布做统计,把经常被一起激活的专家放在同一张卡上,减少跨卡通信。这一步对推理吞吐的影响很直接:测试中,负载均衡做得好与不好,端到端吞吐差距能到30%以上。
5.2 量化友好的路由设计
还有一个被论文和框架文档反复提及的细节:量化后的路由器要专门校准。路由器的输出是一个概率分布,用来决定token去哪些专家,如果这个概率分布被量化误差干扰,某些边缘情况可能被误送到质量较差的专家,最终回复质量下降的感知会非常明显。
所以Kimi这类量产的MoE方案里,路由部分通常保留较高的精度(比如FP16),只对专家网络的权重做4bit量化。这可以解释为什么“用INT4存权重但模型还能保持高智商”,因为真正决定“谁上场”的部分是毫发无损的。做部署的时候,千万别为了省那点显存把路由器也量化成4bit,我实测过,确实会出怪问题。
5.3 在推理框架里做MoE量化配置的实操建议
如果你用的是常见推理框架,例如vLLM、SGLang或TensorRT-LLM,落地W4A8时一般会这样配置:
- 把单个专家层视为独立的Linear层做分组量化,group size通常选128或256。group越小,量化越精准,但存储开销也会略增(需要存更多scale)。
- 激活量化策略选动态per-token量化,scale通过kernel在forward时实时计算。
- 对Attention模块的KV Cache做INT8静态量化,用少量校准数据确定per-head的scale。
- 路由器保持FP16/BF16,不参与4bit量化。
- 所有Int8矩阵乘走Tensor Core,确保数据在fp16/bf16和int8之间转换时有高效的CUDA kernel处理。
以vLLM为例,加载一个4bit权重的MoE模型,权重目录里一般会包含quantize_config.json,里面记录quant_method、group_size、activation_scheme等参数。你在部署时要注意核对quant_method是不是支持W4A8的kernel路径,有些框架的4bit实现默认是W4A16,需要手动开启或选择支持W4A8的预编译版本。
6. 实操排坑实录:我在部署W4A8 MoE时踩过的5个坑
6.1 显存计算和实际占用永远对不上
很多人拿着4bit存储的账本,以为2.7T参数只要1.35TB显存就一定够跑,结果加载的时候直接OOM。为什么?因为权重存储只是其中一部分。你还需要给模型的中间激活值、KV Cache、优化器状态(训练的话)留出空间。此外,CUDA context本身每个进程要吃几百MB到1GB,多卡通信缓存也很吃内存。
实操建议:先按“权重显存 + KV Cache + 激活峰值”三块估算,再额外留20%冗余。如果只是推理且不做大batch,权重占1.35TB,KV Cache按上下文长度预估100GB上下,激活峰值大约几十GB,宽松一点算,1.6TB是安全线。
6.2 4bit权重直接反量化到INT8后精度崩了
这是我很长一段时间的痛。用AWQ量化时,如果激活值的范围没有校准好,INT8的scale会变得偏大或偏小,最终反量化回INT8参与矩阵乘时,误差会被放大。后来发现解决思路是把量化校准的重点从“权重分布”转移到“激活分布”上,要让校准集尽量覆盖线上真实输入的场景。
此外,检查一下kernel路径是否真的走了INT8矩阵乘,有些框架可能会在“4bit权重”加载后,自动把反量化的精度直接提到FP16,即退化成W4A16。这样精度是稳了,但速度没有任何提升,你要的W4A8等于白搭。排查方法很简单:看profiling结果中INT8 Tensor Core的占用率。
6.3 “冷”专家带来的碎片化计算让INT8加速形同虚设
MoE推理时如果某个专家只被很少的token命中,矩阵乘的K维度就会很小。INT8的Tensor Core虽然快,但只有在矩阵乘规模足够大、数据能灌满计算单元时才有加速优势。token数太少反而会因为量化/反量化的额外开销拖慢速度。
我的做法是对路由分布做统计后,进行一次专家重组:把高频专家均匀分布到各卡上,让每张卡的算力负载都接近。vLLM和SGLang里都支持配置专家的显存排布,值得好好调一调。实测中,光这一项就能把整体生成速度提升20%以上。
6.4 长上下文场景下,KV Cache INT8是必要但必须谨慎的优化
前文提过,上下文拉长之后,KV Cache的显存压力是压倒性的。KV Cache用INT8量化,看似只是把一个2字节的value变成1字节,细节上却有三点要注意:
- 一是attention score对精度极敏感,KV Cache的误差会直接影响注意力分布;
- 二是batch size一大,各种per-head的scale叠加起来,会带来奇怪的偏差;
- 三是目前很多框架的INT8 KV Cache只在部分GPU架构上被优化过,切换设备后速度可能反而变慢。
我自己的建议是:默认先用静态per-channel量化,校准数据选1000条左右有代表性的内容;如果出现明显的质量下降,再退回到FP16的KV Cache,毕竟KV Cache的量化是“锦上添花”而非“雪中送炭”,保质量优先。
6.5 安装推理框架时预编译包“伪支持”W4A8
这个坑非常隐蔽。有些框架的预编译包已经包含了对4bit权重的支持,加载模型也不报警,但当你深入看kernel实现时,发现它只是把4bit反量化回FP16做矩阵乘,完全没走INT8 Tensor Core。也就是说,在框架层面,W4A8这个“4bit存储+8bit计算”的组合并不是默认标配,而需要特定编译选项或自定义算子。
遇到这种情况,建议优先选择那些明确支持W4A8(例如TensorRT-LLM的MoE量化路径、以及SGLang里针对Moe的W4A16/W4A8实现),或者参考HuggingFace模型仓库里发布者给出的推荐框架版本。省得折腾半天发现跑了个寂寞。
6.6 附录:几个量化名词的速查补充
聊了这么多,怕有些朋友对基础概念还不太牢靠,这里把容易混淆的几个词一并说清楚:
- INT8 vs FP8:INT8是8bit整数,FP8是8bit浮点(E4M3/E5M2两种格式)。INT8适合表示范围可控、分布均匀的值;FP8动态范围大但量化粒度相对粗。
- INT4 vs FP4:INT4是4bit整数,FP4是4bit浮点(由1bit符号、2bit指数、1bit尾数组成,表达范围很大但精度极低)。目前主流模型权重量化多用INT4/FP4的混合方案,具体看实现。
- BF16 vs FP16:BF16与FP32有相同的指数范围,表示很大或很小的数不容易溢出;FP16尾数精度更高,适合范围稳定的情况。大模型混合训练多数用BF16,推理时BF16的矩阵乘效率也更有优势。
- 静态量化 vs 动态量化:静态量化用校准集提前算好scale,运行时不再计算,适合权重和KV Cache;动态量化在运行时根据实时数据算scale,精度更高但有一定开销,适合激活值。
7. 最后分享一点实测体会
我自己在部署MoE模型的路上真金白银踩出来的感受是:W4A8不是天上掉下来的万能药,而是一套需要整个软件栈配合才能发挥力量的系统工程。你得同时处理好存储精度、计算精度、显存开销、负载均衡和框架兼容性,才能让一个几千亿参数的巨型模型在8卡机器上维持“能看”的生成质量和“能打”的吞吐量。相比W4A16,W4A8的实现在推理框架里遇到的坑更多,但一旦跑通,收益是实打实的。我个人建议,如果你只是想本地体验Kimi这级别模型的效果,先从成熟的W4A16方案上车,熟悉了量化原理之后再切W4A8,会少掉很多头发。
如果你已经在用W4A8方案部署MoE模型,欢迎在评论区说说你用的是哪套推理栈,踩过哪些坑,大家一起攒一份真正能落地的避坑手册。后面我如果继续调试Kimi或类似架构的模型,也会继续在这里同步实操记录。