最近圈子里聊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的稠密模型还要快这就是MoEMixture 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.4TBINT8格式1字节/参数显存需求 2.7T * 1 2.7TBINT4/4bit格式0.5字节/参数显存需求 2.7T * 0.5 1.35TB如果是8卡H10080GB每张总显存是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.5scale大概就是1.1恢复出来的近似值会有一点点误差。这种做法的本质就是主动丢弃精度冗余。神经网络权重本身有一定冗余通常服从类正态分布绝大部分权重集中在均值附近。对权重做4bit量化等于只保留“大趋势”砍掉“微调细节”。大量实验表明4bit量化对模型精度的影响在多数任务上可以控制在1-2%以内这点损失换来的显存节省是巨大的。2.2 权重量化的三种范式PTQ、QAT和GPTQ实际部署中4bit量化不是一拍脑袋直接做min-max映射就完事的尤其是大模型。常用的方案有这么几类PTQPost-Training Quantization训练后直接量化不重新训练。速度快但精度损失可能偏大需要配合校准集来调整量化的scale和零点。QATQuantization-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维度用动态scalechannel维度用静态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是浮点数格式有指数位和尾数位能表达较大范围但精度粒度不如INT8INT8是等间距整数格式在数值范围适中的情况下粒度更细更均匀。激活值有离群值对动态范围的要求高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和计算缓冲。如果要把显存降到两张A100160GB那就要做更激进的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单位是2K和V各一份上下文长度32Kbatch 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精度损失W16A16BF16/FP162字节/参数FP165.4TB1.0x无W8A8INT81字节/参数INT82.7TB1.4~1.6x较小W4A164bit存储FP16计算0.5字节/参数FP161.35TB0.9~1.1x小W4A84bit存储INT8计算0.5字节/参数INT81.35TB1.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.35TBKV 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 FP8INT8是8bit整数FP8是8bit浮点E4M3/E5M2两种格式。INT8适合表示范围可控、分布均匀的值FP8动态范围大但量化粒度相对粗。INT4 vs FP4INT4是4bit整数FP4是4bit浮点由1bit符号、2bit指数、1bit尾数组成表达范围很大但精度极低。目前主流模型权重量化多用INT4/FP4的混合方案具体看实现。BF16 vs FP16BF16与FP32有相同的指数范围表示很大或很小的数不容易溢出FP16尾数精度更高适合范围稳定的情况。大模型混合训练多数用BF16推理时BF16的矩阵乘效率也更有优势。静态量化 vs 动态量化静态量化用校准集提前算好scale运行时不再计算适合权重和KV Cache动态量化在运行时根据实时数据算scale精度更高但有一定开销适合激活值。7. 最后分享一点实测体会我自己在部署MoE模型的路上真金白银踩出来的感受是W4A8不是天上掉下来的万能药而是一套需要整个软件栈配合才能发挥力量的系统工程。你得同时处理好存储精度、计算精度、显存开销、负载均衡和框架兼容性才能让一个几千亿参数的巨型模型在8卡机器上维持“能看”的生成质量和“能打”的吞吐量。相比W4A16W4A8的实现在推理框架里遇到的坑更多但一旦跑通收益是实打实的。我个人建议如果你只是想本地体验Kimi这级别模型的效果先从成熟的W4A16方案上车熟悉了量化原理之后再切W4A8会少掉很多头发。如果你已经在用W4A8方案部署MoE模型欢迎在评论区说说你用的是哪套推理栈踩过哪些坑大家一起攒一份真正能落地的避坑手册。后面我如果继续调试Kimi或类似架构的模型也会继续在这里同步实操记录。