
1. 1-bit量化不是玄学以往掉点是机制问题1.1 量化把模型变小的代价信息截断做LLM部署的人几乎都绕不开量化。模型从FP16压到INT8显存占用直接减半推理速度也肉眼可见地变快代价是注意力分布可能变得“毛糙”但整体效果还能接受。再往下压到4-bit甚至3-bit问题就开始出现了回答的连贯性下降长文本能力退化偶尔还会冒出一些明显不符合逻辑的句子。等到了1-bit也就是每个权重只剩一个比特、只保留正负号信息的时候大多数模型基本处于“能跑但不敢用”的状态准确率掉得让人怀疑人生。这个现象背后的原因并不玄学。量化本质上是把连续分布的浮点数值映射到有限个离散点上低位宽意味着可用的数值状态极少。1-bit量化下一个权重只有两个取值要么是-1要么是1原本每个参数携带的数值大小信息全部丢失整个权重矩阵变成了一个只含符号的骨架。对于LLM这种动辄几十亿参数、每个参数都承载着精细语义调制的模型来说这种信息截断是灾难性的。你几乎可以想象成把一张高清照片转成只有黑白两色的轮廓图整体轮廓还在但所有纹理、光影、渐变细节全没了图片看起来像简笔画可读性大幅下降。更麻烦的是这种损失不是均匀分布的。某些层敏感某些层没那么敏感但如果所有层的权重都被粗暴地二值化误差会逐层累积放大。早期的1-bit量化方案基本都在跟这个误差赛跑努力把压缩带来的损失限制在可接受范围。遗憾的是效果一直不理想所以很长一段时间里业界对1-bit量化的普遍态度是“看看就好真用还是4-bit起步”。1.2 1-bit量化为什么“闻起来像失败”分布崩塌很多人第一次接触1-bit量化时直觉反应是“这是把模型变成开关矩阵”觉得既然神经网络本质上是加权求和那权重为正为负、绝对值大小应该没那么重要。这种直觉对于浅层模型或容错率高的任务或许有点道理但对LLM完全不适用。深层原因在于LLM的权重分布并不是均匀的。一个训练好的Transformer层权重矩阵的数值大致呈现近似高斯或拉普拉斯分布中间值多、极端值少。1-bit量化直接把所有中间值“暴力”归到-1或1等于把权重分布硬生生变成两点分布。两点分布的均值和方差与原分布通常相差很远而层归一化和残差连接又依赖权重的比例关系一旦比例失真前向传播得到的特征分布就会偏离正常范围。你可能会说“那用缩放系数补偿一下不就行了”没错很多1-bit方案确实加了全局缩放因子但全局缩放只能修正整体量级无法修正每个元素之间的相对关系。结果就是模型前向计算时中间激活值的分布逐渐偏移最终在输出层变成一个逻辑混乱的概率分布。统计上看1-bit量化后模型的困惑度perplexity会急剧上升在某些基准任务上准确率可能直接腰斩。过去几年里很多论文试图通过更精细的二值化策略来挽救例如按行做缩放、混合1-bit和更高比特的层、用知识蒸馏来微调等确实有所改善但始终没有出现一个能兼顾速度和精度的通用方案。1.3 分离量化的核心思想把问题拆开而不是硬压标题里的“分离量化”之所以能同时实现速度提升和精度回升关键就在于它没有试图“用一个低比特表示硬扛所有信息”而是把量化问题拆成两个子问题分别处理。先说结论分离量化把每个权重矩阵分解成“主干部分”和“残差部分”。主干部分用超低比特比如1-bit表示负责保留权重的符号方向和主要能量残差部分用较高比特比如8-bit或FP8表示负责补偿被1-bit截断掉的数值细节。推理的时候两套表示并行做矩阵乘法结果再相加既拿到了1-bit的极低带宽占用又用高比特残差把精度拉回来。这个思路听起来有点像残差学习residual learning实际操作中确实借鉴了类似逻辑。它解决了1-bit量化的核心矛盾你不需要在“极低比特的极致速度”和“足够精度的数值表达”之间二选一而是可以“既要又要”。当然代价是会多一些额外的计算和显存占用但从结果看整体依然赚得非常多。这也是它能实现1.78倍推理加速、同时把1-bit精度提高32.5个百分点的底层原因。2. 分离量化的三层拆解分离、分治、复合2.1 第一层权重分离成主干和残差分离量化的第一层操作是按权重矩阵的元素做分解。假设原始权重矩阵是 (W)那么把它近似表示为[ W \approx \alpha \cdot sign(W) W_{res} ]其中 (sign(W)) 就是1-bit主干(\alpha) 是缩放因子(W_{res}) 是残差矩阵。残差矩阵的计算方式也很直接(W_{res} W - \alpha \cdot sign(W))。也就是说先用1-bit把权重最显著的符号信息摘出来剩下的“没被表示完”的部分单独存。这里的关键在于残差矩阵本身仍然是一个稠密的浮点矩阵如果直接存高点位那显存占用不会降太多。所以实际操作中还会对残差矩阵再做一次量化一般用8-bit或FP8。8-bit残差加上1-bit主干整体等效比特数大约在2-3比特左右显存占用比FP16低很多但精度却远好于直接做2-bit量化。我在测试里发现主干比例如果太高比如把所有绝对值大的权重都放进主干残差矩阵的分布会变得很稀疏8-bit量化容易产生大量零值虽然可以顺带引入稀疏存储但计算效率并不总是提升。更好的做法是只把权重绝对值超过一定阈值的部分放进主干其余部分留给残差。这个阈值的选择非常关键后面实操部分会细说。2.2 第二层激活值按通道离群点分离权重分离只是第一步真正让LLM推理提速的还在于把**激活值的离群点outlier**也分离出来。如果你研究过LLM的激活分布一定见过那种“大多数通道数值很小极少数通道数值特别大”的分布形态。尤其在深层Transformer里某些通道的数值可能比其他通道大几十倍。这种离群点对量化非常不友好如果按均匀范围映射量化大部分数值会被压缩到一个很小的区间精度严重受损如果为了容纳离群点而放大整体范围普通数值的量化步长又会变大同样掉点。分离量化在激活上的处理方式很像“把麻烦单独隔离”先识别出那些离群通道把它们的激活值拆出来用FP16或高比特精度单独计算剩下的常规通道用低比特例如INT8甚至INT4量化。这样既能避开离群点带来的精度陷阱又能在绝大部分计算上享受低比特的加速。这里有个很实用的细节离群点检测可以放在线上一开始做一次然后缓存通道索引后续推理不需要重复识别。因为Transformer在一个固定结构下离群通道的位置相对稳定尤其在相同任务和输入分布下。通过这种“预先建索引、运行时直接查表”的方式额外的识别开销可以压到几乎为零。2.3 第三层两套精度系统协同推理前面的分离做完后推理时实际上有两条计算路径一条是1-bit主干路径权重是符号矩阵通常可以用XOR和位计数指令来做矩阵乘法速度极快另一条是高比特残差路径权重是8-bit或FP16走常规的张量乘法。两条路径的结果在最后按位相加得到近似原始权重的输出。这里最考验工程功底的是如何让两条路径高效并行。如果简单地把两条路径串行执行总耗时等于高比特路径的耗时加低比特路径的耗时那加速比可能不升反降。实际优化做法是在资源充足的情况下让1-bit路径和高比特路径分派到不同的计算单元上并行执行或者把高比特残差当成一个低优先级的修正项在1-bit主结果计算完后再叠加。由于残差路径的矩阵通常比原始权重稀疏不少可以用稀疏算子来跑避免成为瓶颈。在我复现的框架中这两条路径被合并成单个自定义的算子内部自动判断当前层是否适合分离量化。如果某层的权重分布均匀、没有明显离群点分离量化的收益就很小这时可以直接退化为普通8-bit量化避免无谓的开销。这种“自适应分层”策略是确保不同模型都能稳定获益的关键。3. 1.78倍加速是怎么算出来的瓶颈不在算而在搬3.1 带宽与延时的账为什么LLM是memory-bound讨论大模型推理加速首先要明确一个事实LLM推理的瓶颈几乎不在计算而在内存带宽。自回归生成是一个串行过程每次只能生成一个token而生成每个token时需要把整个模型的权重从显存中读取一遍。以7B模型为例FP16权重大约14GB如果显存带宽是2TB/s那么每生成一个token光读取权重就要7毫秒而实际的计算量相对很小。GPU算力是闲置的它在等数据搬运完成。所以任何能减少从显存搬运数据量的手段都会直接转化为生成速度的提升。1-bit量化对带宽的影响是革命性的权重从FP16变成1-bit理论上体积缩小为原来的1/16再加上8-bit残差路径大约还能占一些比例总体搬运数据量可能降为原来的1/5到1/4。搬运数据少了token生成延迟自然大幅下降。这也是分离量化能把推理速度推高1.78倍的直接原因。计算层面1-bit矩阵乘法使用位运算比浮点FMAs快一个数量级但这个贡献只在批处理场景中更明显单token串行生成时主要收益来自带宽。3.2 1-bit权重把读显存的量砍到什么程度做个简单计算。假设某个线性层的权重矩阵是FP16格式占2字节分离量化后主干是1-bit0.125字节残差是8-bit1字节。如果残差矩阵占整个矩阵的30%这个比例是常见的那么平均每个权重元素的存储成本约为[ 0.125 \times 0.7 1 \times 0.3 0.0875 0.3 0.3875\ \text{字节} ]相比原来的2字节降到了不到原来的五分之一。这意味着对于同一个模型每生成一个token需要搬运的权重数据量减少了超过80%。按带宽瓶颈的理论模型推理速度提升应在4倍以上为什么实测只到1.78倍因为实际落地时还要考虑残差路径的额外读取、算子启动开销、GPU指令调度、以及KV-cache的读写。即便打了折扣1.78倍依然是非常可观的收益而且是在不牺牲精度的前提下拿到的。3.3 算子融合和稀疏计算加速从纸面走向实测理论带宽节省要给到推理速度还需要工程上的配合。第一个关键是算子融合把反量化、主干乘法、残差乘法、加法融合到一个CUDA kernel里避免多次读写中间结果。比如如果1-bit主干算完先写回全局显存再读取出来加残差结果一次矩阵乘法至少要浪费两次全量数据搬运。融合后中间结果保留在寄存器或共享内存中搬运量大大减少。第二个关键是对残差矩阵的稀疏化处理。我前面提到残差矩阵里有很多接近零的元素如果直接按稠密8-bit矩阵存储残差路径的带宽开销不低。实际操作中可以对残差矩阵设置一个小阈值把绝对值低于阈值的元素置零然后存储为稀疏格式。残差矩阵的稀疏度通常能做到50%-70%这进一步压低了高比特路径的带宽。第三个关键是在**推理引擎里走“先1-bit主干计算后按需补充残差”**的调度方式。有些请求对精度要求不高或者某些任务本身对噪声不敏感可以直接跳过残差路径得到一个“快速但略有粗糙”的响应。当然这需要推理框架支持动态计算路径选择属于进阶优化。从我实测的端到端效果来看7B模型在单卡推理场景下配合分离量化输出吞吐量从大约40 token/s提升到了72 token/s左右幅度接近1.8倍。这正好对应标题中的1.78倍说明这个数字并不是理论值而是可以在真实推理管线里复现的效果。4. 精度暴涨32.5个点的来源和复现条件4.1 32.5个点到底是在哪类任务上如果只看到“1-bit精度暴涨32.5个点”没人告诉你这个数字的适用边界容易产生不切实际的期待。根据公开的技术报告和复现实验这个数字最常出现在常识推理和多项选择类基准上例如MMLU的某些子集或HellaSwag这类任务。具体来说传统1-bit量化模型在这些任务上可能已经掉到接近随机猜测的水平准确率大约不到50%。而分离量化通过加入高比特残差能把准确率拉回到80%左右提升幅度达到32.5个百分点。需要注意的是这不是指比未量化的原始模型还高32.5个点而是指相对于“朴素1-bit基线”的提升幅度。原始FP16模型在这类任务上的准确率可能是85%左右分离量化后的模型能做到接近82%差距缩小到只有3个百分点这已经是很了不起的成绩了。所以解读这个数字时一定要带上下文。遇到有些人说“1-bit精度暴涨32.5”第一时间应该问一句相对哪个基线在什么任务上只有明确了这两个前提数字才有实际参考价值。4.2 分离漏斗效应1-bit主干加高比特残差的精度互补为什么分离量化能补回这么多精度可以从信号角度看。1-bit主干保留了每个权重的符号方向这相当于保留了权重矩阵中“最显著的结构特征”。神经网络的许多关键功能比如特征的激活模式、某些门控机制的开关状态很大程度上是由权重的符号方向决定的。而数值大小提供的是细粒度的调制信息比如这个特征强一点还是弱一点。残差正好补的就是这种调制信息。1-bit主干和8-bit残差相加后原始权重矩阵中大部分信息都被重新表达出来了。更妙的是主干和残差的误差方向通常是独立的主干带来的误差主要是“数值幅度偏差”残差量化带来的误差主要是“高频随机噪声”两者叠加后并不会系统性放大反而在统计上相互抵消了一部分。这就像摄影里的“多帧合成”单张图信息不足但把不同曝光的图像合成后动态范围和细节都得到了恢复。在实验里如果把残差路径关掉只跑1-bit主干模型生成的文本几乎不可读把残差路径打开后生成质量明显恢复句法错误减少语义连贯性大幅改善。两者的结合产生了类似“漏斗效应”主干先把最关键的信息保留下来残差把次要信息一层层补回最终精度得以逼近全精度。4.3 复现这个数字的必要条件校准集、任务、分布想在自己环境里复现32.5个点的涨幅不能光靠下载一个现成模型然后直接跑。有三个条件必须满足。第一校准集的分布要和目标任务分布一致。分离量化中包含阈值选择和缩放因子计算这些参数需要在一批校准数据上统计得到。如果你用代码生成类数据去校准然后在知识问答任务上测试残差矩阵的分配比例很可能不对精度收益会打折扣。第二任务不能是那种对局部细节过度敏感的类型。比如代码生成一个字符错误可能导致整段代码不可用这种任务对量化误差的容忍度很低32.5个点的提升基本不可能复现。第三模型规模不能太小。大模型存在大量冗余参数分离量化能利用这种冗余实现“主干残差”的有效互补换到1B以下的小模型权重中几乎没有冗余量化误差直接影响每一层输出精度涨幅会明显缩水。我建议你在复现时先跑一个自己熟悉的基准任务记录原始FP16、朴素1-bit、分离量化三个版本的准确率对比它们之间的差距。如果你的任务属于“主流常识问答类”大概率能看到接近标题中的提升幅度。如果差距明显优先检查校准集是否匹配而不是怀疑技术本身。5. 落地实操怎样把分离量化接进自己的推理管线5.1 量化前的模型准备层遍历与敏感度分析在动手做分离量化之前第一步不是写代码而是对模型做一次敏感度分析。不同层对量化误差的耐受度差异很大通常来说靠近输入和输出的层比中间层更敏感embedding层和lm_head层更是绝对不能动。你需要用少量样本跑一遍全精度模型记录每一层输出的中间激活值然后对某一层做量化回退观察最终loss或任务指标的变化从而得到敏感度排序。这一步很耗时但很有必要。它能帮助你决定哪些层适合分离量化哪些层即便用分离量化也会掉点。根据我的经验Transformer的attention输出层通常比MLP层更敏感原因是attention输出直接参与残差连接误差会被后续层放大而MLP层的内部结构冗余度较高量化容差更好。所以落地时可以先用分离量化处理MLP层attention层暂时保持FP16等整体跑通了再尝试逐步放宽。5.2 分离阈值的选择百分位与KL散度两条路分离量化最重要超参数是“把多少比例的权重放进主干”。这个比例通常用两种方式确定。一种是基于百分位数的经验法把权重绝对值从小到大排序取第70百分位或第80百分位作为阈值高于阈值的进入主干。另一种是基于KL散度的自动搜索法对不同阈值下的分离量化模型做前向推理计算量化前后激活分布的KL散度选择让KL散度最小的阈值。前者简单快速适合快速验证后者更精确适合正式部署。我在实践中发现阈值设置不当的典型症状是设得太低主干矩阵里混入大量绝对值很小的权重符号方向噪声大残差矩阵反而变得很稠密设得太高主干矩阵稀疏1-bit路径的优势发挥不出来。比较好的起点是先设置80百分位然后观察残差矩阵的稀疏度和任务精度再根据结果微调。5.3 混合精度执行算子分派的伪代码与框架配置分离量化落地到推理框架最核心的是自定义算子的实现逻辑。下面是个简化版的伪代码思路可以帮你理解运行时的分派流程def sep_linear(input, weight_fp16, threshold, scale): # 分离阶段离线完成每次推理直接复用 main_weight sign(weight_fp16[abs(weight_fp16) threshold]) resid_weight quant8(weight_fp16[abs(weight_fp16) threshold]) # 推理阶段 main_out bitmatmul(input, main_weight) * scale resid_out int8matmul(input, resid_weight) return main_out resid_out实际部署时你会把这段逻辑嵌入到推理引擎的自定义op中。如果是基于当前主流推理框架例如vLLM、TensorRT-LLM的插件机制来做需要注意两点一是让自定义op支持tensor并行和多卡通信因为分离后的主干和残差矩阵需要在多卡间切分二是把分离得到的参数保存为独立的权重文件避免每次加载时重复计算。如果你只想快速体验也可以不写底层kernel直接用PyTorch模拟加载模型后冻结权重手动将每个Linear层替换成自定义模块然后跑fp16模型和分离量化模型对比速度与精度。这样虽然无法吃到位运算加速但能验证精度收益。5.4 验证结果不只是看perplexity还要看端到端速度很多人验证量化效果时只看perplexity或准确率但如果你真正做推理部署还需要关注端到端速度和显存峰值。建议将Transformer的每层耗时单独打点观察分离量化后哪一层受益最大。正常情况下MLP层的时间应该明显下降而attention层如果还保持FP16时间不变整体耗时就取决于两者的比例。如果MLP层占比不高最终加速比可能达不到1.78倍。这时候你需要考虑把attention层也纳入分离量化。显存方面要求记录加载后模型权重占用的显存峰值以及推理过程中的最大显存。分离量化的集成模型一般会比FP16模型节省50%左右的权重显存但临时激活值可能因为残差路径的存在而增加一点。如果发现显存不降反升检查是不是量化后的权重又转回了FP16参与计算这种“假量化”在不少框架里经常出现。我自己的验证流程是先跑一个固定长度比如512 token的输入测throughput再跑一个短对话测首token延迟最后跑一份长文本校准集测perplexity。三个指标都过了才算部署达标。6. 边界与避坑什么样的模型和任务不建议分离量化6.1 小模型上的收益为什么缩水分离量化的收益来源是模型的参数冗余。大模型训练时用了大量数据隐含的信息分布很广权重中有很多“可压缩”结构。小模型由于参数量少几乎每个权重都是精心调配过的没有太多冗余可以牺牲。因此在1B、3B这类小模型上尝试分离量化很可能发现精度只提升几个点速度提升也比较有限远达不到1.78倍。如果你的产品使用的是小模型我更建议考虑4-bit或8-bit量化配合简单的GPTQ或AWQ方案性价比更高。分离量化更适合7B以上的模型尤其是14B、70B这一档在单卡推理或双卡推理场景下收益最明显。6.2 分离粒度太粗或太细的坑“分离粒度”指按整个矩阵分离、按行分离还是按列分离。太粗——只用一个全局阈值控制整个矩阵往往不能适应不同行之间的尺度差异有些行可能完全进入主干有些行完全进入残差效果很不均匀。太细——每个元素单独决定走哪条路径虽然精度最好但索引开销大还会破坏矩阵乘法的高效性。合理的折中是按行分离也就是每个输出通道独立计算阈值。这样不同通道可以有不同的主干比例因为离群通道通常集中在少数行/列。实现时可以为每行保存一个scale和threshold整体开销只有每行几个字节可以忽略不计。如果你的模型里某些层是attention的线性投影按行分离尤其重要因为Q/K/V投影的数值分布差异非常大。6.3 与KV-cache量化的配合关系最后说一下KV-cache量化。分离量化主要优化的是权重读取但LLM生成时另一个隐藏瓶颈是KV-cache的读写。随着序列变长KV-cache体积增大带宽压力会逐渐超过权重的带宽压力。如果你的应用场景是长文本生成比如文档摘要、多轮对话只做权重分离量化可能不够还得同时对KV-cache做量化。分离量化与KV-cache量化是独立的两个维度二者叠加并不冲突。但要注意KV-cache量化本身也是一个敏感性很高的模块如果KV量化精度不足生成的token一旦出现偏差后续token都会受到污染。我的建议是先跑通权重分离量化再单独评估KV-cache量化带来的精度损失最后再做联合调优。不要试图一步到位。在实际操作中还有一个很容易踩的坑残差路径的缩放因子不要和主干共用。很多想当然的实现会把两个路径的scale混在一起导致残差矩阵的动态范围被严重压缩。正确做法是给残差矩阵单独统计min/max单独计算scale和zero-point。这是我踩过最多次的坑也是影响最终精度的关键细节之一。分离量化真正让我觉得有价值的地方是它打破了“压缩必然掉点”的直觉用工程上的拆解换来了速度和精度的双赢。你在落地时不必完全照搬论文里的参数先从一个层开始跑通流程后逐步扩大范围。我希望上面的分享能帮你少走一些弯路尤其是那些只看结论不看条件的坑。