大模型部署优化实战:从量化剪枝到微调补偿的流水线
发布时间:2026/10/1 13:50:18来源:尧图网络
上个月我把 Qwen2-7B-Instruct 从 FP16 压到 INT4模型文件从 14GB 缩到 4GB 出头一张 24GB 显卡上同时跑推理服务和几十路并发请求显存居然还能剩下一大截。整个过程没有写什么魔法代码靠的就是我手头这套叫 Model-Optimizer 的工具项目沉淀出来的优化流水线。今天就把这套东西从头到尾拆开讲讲包括它是怎么设计的、每个环节在做什么、关键参数怎么定以及我实测过程中踩过的坑。做模型部署的同行应该都有同感模型评估指标再漂亮上不了线等于白做。线上单卡经常只有 24GB 或 48GB 显存有些场景甚至是纯 CPU而开源模型动辄 70 亿、130 亿参数。FP16 权重一加载7B 模型光 weights 就是 14GB13B 差不多 26GB还没算 KV cache 和中间激活OOM 几乎是必然的。就算显存勉强放下大模型逐 token 生成的推理模式又是典型的显存带宽瓶颈——每出一个 token 都要把全部权重读一遍模型越大越慢这笔账怎么算都得优化。Model-Optimizer 不是某个厂商的重量级平台而是一个偏工程向的轻量工具集。它把 PTQ 量化GPTQ、AWQ、GGUF 那套、剪枝SparseGPT / Wanda / 结构化剪枝、知识蒸馏、LoRA 微调补偿以及 vLLM、llama.cpp、ONNX Runtime、TensorRT-LLM 这些推理引擎的导出环节串成一条带评估闭环的流水线。每个环节跑完都会自动对比优化前后的困惑度和下游任务分数压完能不能用、掉了多少一目了然。这篇文章适合正在折腾模型部署、显存优化和边缘推理的工程师也适合刚入行想系统搞懂大模型优化有哪些手段的新手。1. 为什么需要 Model-Optimizer1.1 大模型落地的三个硬约束显存、带宽、成本先算一笔显存账。一个 7B 参数模型FP16 权重占 7e9×2 字节约 14GB13B 就是 26GB70B 直接飙到 140GB。权重还不是全部KV cache 在长上下文场景下同样吃显存。以 7B 模型常见配置估算序列长度拉到 4096单个请求的 KV cache 要占几百 MB 到 1GB 级别并发一上来几十 GB 显存瞬间没了。所以显存优化从来不只是压权重还要管 KV cache 和激活值这三个口子都得堵。第二个约束是带宽。解码阶段是逐 token 生成的每生成一个新 token 都要把所有参数从显存搬到计算单元。FP16 7B 模型一次前向就要搬约 14GB 数据想在 A100 上跑到 30 token/s就需要约 420GB/s 的持续带宽这已经逼近显存带宽的实际天花板。反过来看把权重压成 INT4每 token 只搬 3.5GB同样的设备、同样的带宽生成速度的上限理论上能翻 4 倍。第三个是成本。A100/H100 按小时计费不便宜模型不优化意味着你得租更大的卡、扛更高的并发资源每次推理的边际成本居高不下。对 SaaS 服务和私有化部署来说单卡能扛的 QPS 直接决定单次 API 调用的成本。把这些算明白就知道优化不是锦上添花而是上线前的必修课。1.2 为什么是一条流水线而不是一堆零散脚本我一开始也是一堆零散脚本今天拿 GPTQ 压一个明天拿 SparseGPT 剪一个后天用 TRL 跑个 LoRA。结果就是中间态完全不可追溯A 脚本压完的模型拿给 B 脚本剪各种格式不兼容评估口径也不统一最后根本判断不了是哪一步把效果搞崩的。Model-Optimizer 的核心设计就是把优化动作拆成固定 Stage每个 Stage 的输入输出都是标准格式的模型目录加一份 JSON 评估报告。模型怎么变的、每一步掉了多少分全程有记录。流水线顺序也很有讲究。我最终固定的顺序是诊断 → 量化 → 剪枝 → 蒸馏可选→ 微调补偿 → 评估 → 导出。量化放前面是因为 PTQ 是成本最低、收益最稳定的第一步只动权重的数值表示、不改结构绝大多数模型压到 INT8 几乎无感压到 INT4 也只是轻微退化。剪枝放后面是因为它改变的是权重张量的形状和稀疏度对后续算子融合、kernel 选择影响更大先量化后剪枝可以让误差分摊更可控。蒸馏和微调补偿属于修复阶段等前面压完、评估报告出来再决定要不要做。1.3 和全量微调的边界在哪不少新人会把模型优化和微调混为一谈。本质上两者解决不同的问题微调是让模型学习新能力、新知识或新风格优化是让模型在更少资源下保持原有能力。Model-Optimizer 里也会用到 LoRA但它的角色是补偿——量化、剪枝造成的精度损失通过一小段参数高效微调拉回来一部分而不是教模型新东西。这个定位有个好处补偿微调的学习率、步数和数据都可以标准化不会陷入微调到底调什么的泥潭。全量微调在这条流水线里基本不用。成本高、周期长对权重几乎是重写反而不利于评估优化效果——你没法区分精度回升到底是因为优化误差被修复了还是模型本身被改了。在 Model-Optimizer 的体系里微调永远只做修复不做增强这样才能保证每个 Stage 的效果可归因。2. 核心技术原理与选型思路2.1 量化把连续的浮点值装进离散的整数格量化的本质是用有限的整数去近似连续的浮点值核心公式是 r round(x / scale) zero_pointscale 决定步长zero_point 决定偏移。按对称性分对称量化假设数据关于 0 对称权重多用这个非对称量化多一个 zero_point更适合分布明显偏移的激活值。按粒度分per-tensor 是整层共用一个 scaleper-channel 是每个通道各用一组参数后者精度更高但存储略贵。实际中权重量化基本选 per-channel激活量化多数用 per-tensor 加动态范围。选型上目前主流是三套方案。第一套是 GPTQ基于二次近似用 Hessian 矩阵估计每个权重的敏感度逐层做最优脑手术式的补偿——量化某些权重后调整剩余权重来均摊误差。关键参数是 group_size 和 desc_act。group_size 越小分组越细精度越高但 scale 存储开销越大128 是目前性价比最高的档位32 只在模型对精度极其敏感时才用。desc_act 决定是否按激活值大小对列重排打开后精度更好但部分 kernel 不友好推理时会慢一点。第二套是 AWQ。它统计校准集上的激活值分布找出那些改变某个权重会造成激活值剧变的显著通道对它们单独放大 scale再做 4bit 量化。简单说GPTQ 在误差补偿层面努力AWQ 直接从源头保护敏感参数。实测下来AWQ 对存在明显 outlier 特性的模型更稳某些指令微调模型用 AWQ 压出来的效果明显好于 GPTQ。第三套是 GGUF 家族的 K-quant 方案比如 q4_k_m、q5_k_m。它把张量按重要度拆成不同 block重要部分用更多位数、次要部分用更少位数本质是一种混合精度量化对小模型和 CPU 部署非常友好。这里有个容易忽略的点量化不是把值 clamp 一下就完事真正的工作量在 scale 的计算。scale 来自校准数据校准数据长什么样scale 就偏向什么样。后面实操章节我会专门讲校准集构造。同一个模型别人压完没问题你压完胡言乱语大概率就是校准集翻车了。2.2 剪枝删掉不重要的参数但别轻易上剪枝的目标是把权重矩阵里那些接近零、对输出影响小的参数删掉。非结构化剪枝是逐权重做的稀疏度可以做到 50%-90%但问题是权重变成稀疏散点后通用硬件上很难加速只有特定 kernel 才能吃到红利。比如 Ampere 架构的 2:4 结构化稀疏每 4 个连续权重最多保留 2 个非零满足张量核要求50% 非结构化稀疏率的精度损失通常可控还能实打实加速。结构化剪枝则是直接把整行整列、甚至整层 head 删掉。硬件友好但精度损失大得多一般用于配合蒸馏的小模型替换场景。纯靠剪枝从 7B 砍到 5B 再补训练工程量和风险都很大非必要不用。实操层面常用两个工具SparseGPT 基于 Hessian 逆做一次性剪枝能边剪边补偿剪完后质量更好Wanda 更简单计算每个权重与对应激活幅度的乘积作为重要性分数剪掉分数低的跑得快效果也不错。坦白讲从工程收益看量化带来的压缩比远大于剪枝。剪枝更适合作为量化基础上的一层叠加优化而不是替代方案。如果你的业务推理引擎本来就不支持稀疏计算那剪枝这步可以直接跳过没那么多可纠结的。2.3 知识蒸馏用教师的思考痕迹带学生蒸馏特别适合我就是想换一个更小的模型来承接线上任务的场景。比如你有 FP16 的 8B 教师模型想换一个 3B 学生模型直接让学生在同样数据上从头学效果大概率差一截但让学生去模仿教师模型的输出概率分布效果会好很多。关键是 logits 蒸馏学生损失 α·CE(学生输出真实标签) (1-α)·KL(学生输出教师输出)。KL 散度让学生的输出分布向教师靠拢温度 T 用来软化概率分布让教师模型中不正确答案的相对可能性也能传递给学生。常用 T 在 4-6 之间α 在 0.3-0.7 之间具体要扫几组。蒸馏数据不需要像预训练那么大但覆盖度要够。我会把通用语料和目标任务语料按 3:1 混合通用语料保泛化任务语料保效果。有一个现实问题蒸馏对硬件成本不低因为每一步都要在教师模型上做前向教师越大越贵。所以一定先确认换小模型的收益能覆盖蒸馏成本否则不如直接优化现有大模型少折腾。2.4 微调补偿给受伤的模型做定向修复量化、剪枝后精度一定会掉只是掉多掉少。微调补偿就是在这个阶段用 LoRA 把损失拉回来。LoRA 的核心是冻结原权重、在旁边加低秩分解的增量矩阵W W B·A其中 A 是 d×r、B 是 r×dr 远小于 d。这样只需要训练极少量参数显存和计算成本都很低。在 Model-Optimizer 里我习惯用 QLoRA 方式跑补偿基座已经是 4bit 量化模型直接用 PEFT 挂 LoRA 适配器学习率 1e-4 左右rank 取 32alpha 取 64dropout 0.05拿几千条高质量指令数据跑几百步就停。这里最忌讳的是跑过头——补偿微调一旦步数太多模型开始过拟合训练数据泛化能力反而下降评估分数会出现先升后跌的走势。所以我会每几百步存一个 checkpoint 并跑一次评估用评估曲线决定最终保留哪个版本。3. 全流程实操与关键参数3.1 环境准备锁版本是第一原则我的主力环境是 Ubuntu 22.04 CUDA 12.1 PyTorch 2.2显卡是 RTX 409024GB和一张 A100 80G。在 24GB 单卡上做 7B 模型的 INT4 量化完全够用做到 13B 就要小心一点部分层可能需要 offload 到 CPU。依赖安装如下pip install torch transformers datasets accelerate pip install auto-gptq # GPTQ 量化 pip install autoawq # AWQ 量化 pip install bitsandbytes peft trl # QLoRA 补偿微调 pip install vllm # 推理服务 pip install lm-evaluation-harness # 下游任务评估强烈建议把依赖版本锁死。auto-gptq 和 transformers 的版本兼容性问题非常多升级 transformers 后 GPTQ 模块经常报错最后只能回退到指定版本才能正常加载模型。这个坑我踩了不止一次项目 README 里专门写了一张版本兼容矩阵每次重新部署照抄。3.2 校准集构造128 条样本质量远比数量重要校准集是替模型打样的量化器从校准数据中统计激活分布从而决定 scale 和 zero_point。校准集不是越多越好业界通行的经验是 128 条样本、每条截断到 2048 tokens来源要多样。我用的是 c4 子集加领域语料权重比例 4:1。一个容易犯的错是直接用 wikitext2 做校准然后又用 wikitext2 做评估这等于把考试答案提前给了模型评估出来的 ppl 没有说服力。校准集和评估集必须严格分开。构造代码大概是这样from datasets import load_dataset from itertools import chain def build_calibration_set(tokenizer, n_samples128, seq_len2048): # 混合通用语料和领域语料保证分布多样性 general load_dataset(c4, en, splittrain[:2000], streamingTrue) samples [] buf for i, sample in enumerate(general): buf sample[text] # 拼接截断短文档拼到超过 seq_len 再截断避免 padding 污染统计 while len(samples) n_samples and len(buf) seq_len * 3: block buf[:seq_len * 3] buf buf[seq_len * 3:] tokens tokenizer(block, truncationTrue, max_lengthseq_len, return_tensorspt) samples.append(tokens) if len(samples) n_samples: break return samples注意截断策略。有些文本很短直接截断到 2048 会混入大量 padding token这些 token 没有信息含量却会污染激活统计。我用的是拼接截断先把多个短文档拼到超过 2048 tokens 再截断让每条样本都尽量有实际内容。3.3 GPTQ 量化实操每个参数的代价都要清楚以 Qwen2-7B 为例用 auto-gptq 压到 4bitfrom transformers import AutoTokenizer from auto_gptq import AutoGPTQForCausalLM tokenizer AutoTokenizer.from_pretrained(Qwen/Qwen2-7B-Instruct) calibration_samples build_calibration_set(tokenizer, seq_len2048) model AutoGPTQForCausalLM.from_pretrained( Qwen/Qwen2-7B-Instruct, quantize_configNone, device_mapauto, ) model.quantize( calibration_samples, bits4, group_size128, desc_actTrue, damp_percent0.01, static_groupsFalse, ) model.save_quantized(./qwen2-7b-gptq-int4, use_safetensorsTrue)几个参数逐个说。bits4 不用解释。group_size128 是压缩精度和 scale 存储开销的平衡点。desc_act 如果打开权重列会按激活值排序优先处理能保留激活值大的列不被量化误差污染但对推理 kernel 不友好实测同型号上开启后推理延迟会增加 5%-10%。如果模型本身很稳对精度有信心可以关掉换速度。damp_percent0.01 是给 Hessian 矩阵对角线加阻尼项防止求逆时数值不稳定一般保持默认。static_groups 控制 group 是静态还是动态分配默认 False 即可。量化完的目录里会带 quant_config.json记录所有超参数这是后面排查问题的重要依据。我会顺手把校准集信息也写进 config免得时间久了记不清当时用的什么数据。3.4 AWQ 量化实操与格式选型AWQ 的入口是 autoawqfrom awq import AutoAWQForCausalLM model AutoAWQForCausalLM.from_pretrained(Qwen/Qwen2-7B-Instruct) model.quantize( tokenizer, quant_config{ zero_point: True, q_group_size: 128, w_bit: 4, version: GEMM, }, ) model.save_quantized(./qwen2-7b-awq-int4)AWQ 的权重格式和 GPTQ 不通用所以选型时要先想好推理引擎。vLLM 两种都支持但 TensorRT-LLM 对 AWQ 的支持更顺ONNX Runtime 的某些版本又只认 GPTQ。我的建议如果模型要在 TensorRT-LLM 上跑优先选 AWQ如果要在 vLLM 或 llama.cpp 生态里灵活切换GPTQ 兼容性更好如果部署目标是 CPU直接走 GGUF前面的 GPTQ/AWQ 流程都省了。3.5 剪枝实操何时值得做、怎么做剪枝环节我用得比较克制。多数场景下量化到 INT4 已经够解决显存和带宽问题再剪枝会增加一层误差来源收益却不是线性的。只有在目标显存非常紧张、或者推理引擎本来就支持稀疏计算的情况下才加剪枝。以 Wanda 为例核心流程是先在校准集上收集激活幅度计算 importance score再按目标稀疏度把每个权重矩阵里分数最低的部分置零def wanda_prune(model, calibration_activations, sparsity0.25): for name, module in model.named_modules(): if isinstance(module, nn.Linear): w module.weight.data # 激活幅度加权的重要性分数 score w.abs() * calibration_activations[name].abs().unsqueeze(1) threshold torch.quantile(score.flatten(), sparsity) mask score threshold module.weight.data[~mask] 0.0 return model两个注意点。第一剪枝后的稀疏权重如果只是置零、没有真正剪掉维度模型的参数总量不变推理路径也不会变快必须交给支持稀疏计算的 kernel 才能吃到硬件红利。第二顺序上我推荐先量化、后剪枝。量化误差和剪枝误差叠加时SparseGPT 可以在剪枝的同时对残差做量化补偿效果优于先剪枝后量化。3.6 蒸馏实操别忘了 temperature 平方蒸馏在 Model-Optimizer 里不是必经环节。我的判断标准很直接线上确实要用更小的模型承接任务才启动蒸馏。实操上用自定义 lossdef distillation_loss(student_logits, teacher_logits, labels, temperature5.0, alpha0.5): ce_loss nn.CrossEntropyLoss()(student_logits.view(-1, vocab_size), labels.view(-1)) kl_loss nn.KLDivLoss(reductionbatchmean)( F.log_softmax(student_logits / temperature, dim-1), F.softmax(teacher_logits / temperature, dim-1), ) return alpha * ce_loss (1 - alpha) * temperature**2 * kl_loss这里有个很多人不知道的细节KL 项要乘 temperature²。logits 被温度放大后梯度尺度变了不乘这个系数KL 的影响力会被错误放大乘回去之后两个 loss 的量级才一致alpha 才有意义。另外教师模型的 logits 建议提前离线算好存盘训练时直接读不要实时 forward。特别是 8B 教师 3B 学生这种组合教师前向是整个蒸馏的瓶颈离线预计算能省下大量显存和时间。3.7 评估闭环每一步都要给自己一个交代Model-Optimizer 里最不讨喜但最有价值的模块就是评估。没有评估的优化等于盲人开车。每执行完一个 Stage 我自动跑三组评估。第一组是 perplexity。用 lm-evaluation-harness 或者自定义脚本在 wikitext2、c4 子集上算困惑度。数据必须和校准集隔离否则结果虚高。ppl 的绝对涨跌不能完全代表下游任务表现但它是成本最低的感冒探测器——ppl 指标崩了后面任务分数大概率也崩。第二组是下游任务。轻量场景跑几个关键任务就行MMLU 看常识和推理GSM8K 看数学链式推理CMMLU 或 CEval 看中文能力。任务不在多选和业务最相关的 2-4 个即可。第三组是性能画像。测量模型文件大小、加载后显存占用、单请求延迟TTFT、生成吞吐tokens/s、并发下的 QPS。三组结果汇总成 JSON 报告存入优化目录方便横向对比。这套习惯坚持下来优化不再凭感觉每个决策都有数据背书。3.8 导出与部署最后的兼容性把关评估通过后进导出。vLLM 场景最简单GPTQ 格式直接扔给 serve 命令vllm serve ./qwen2-7b-gptq-int4 \ --quantization gptq \ --max-model-len 4096 \ --gpu-memory-utilization 0.9 \ --max-num-seqs 32如果是 GGUF需要先用 llama.cpp 的 convert 脚本把 HF 模型转成 fp16 GGUF再用 llama-quantize 压成目标量化格式python convert_hf_to_gguf.py ./qwen2-7b-fp16 --outfile qwen2-7b.gguf ./llama-quantize qwen2-7b.gguf qwen2-7b-q4_k_m.gguf q4_k_mGGUF 格式选择上我常用 q4_k_m 或 q5_k_m。q4_k_m 是 4bit 和更高精度 block 的混合视觉上接近 INT4但在长文本场景下稳定性更好。q5_k_m 文件大一点精度接近 INT8对效果敏感的业务优先用它。导出之后一定找一个和业务最像的 prompt 连测 20 条人工看一遍输出防止格式转换把 tokenizer 或特殊 token 弄坏。这个步骤看着土实际能拦住绝大多数部署事故。4. 实测案例把 7B 模型压进 24GB 显卡4.1 基线设置与目标用 Qwen2-7B-Instruct 跑一次完整流程。基线是 FP16目标是单卡 24GB、vLLM 部署、支持 16 路并发、生成质量尽量不掉。基线数据模型文件 14.4GBwikitext2 ppl 7.83MMLU 59.2GSM8K 59.8 左右。说明一下不同模型版本和评测环境数字会有差异大家看趋势就行结论是可复现的。4.2 分阶段优化结果阶段模型文件权重显存wikitext2 pplMMLUGSM8K相对基线退化FP16 基线14.4GB~14.4GB7.8359.259.8-GPTQ INT4 group1284.1GB~4.1GB8.0158.758.9温和INT4 Wanda 25% 稀疏3.1GB~3.1GB8.3257.156.4明显但可用补偿微调 LoRA r32 500步3.1GB适配器~3.1GB8.0658.658.5回到接近 INT4趋势很清楚INT4 相对基线退化很小MMLU 掉 0.5 个点以内再加 25% 稀疏度退化被放大到 MMLU 掉 2 个点但 500 步 LoRA 补偿微调能把大部分退化拉回 INT4 水平代价只是新增一个几十 MB 的适配器文件。4.3 部署效果与取舍最终生产版本用的是 INT4 补偿微调剪枝那步因为业务端无法充分利用稀疏 kernel收益不大舍弃了。部署环境是 RTX 4090 24GBvLLM 0.5.xmax-model-len 4096gpu-memory-utilization 0.9最大并发 32。实测单路生成吞吐约 45-50 tokens/s16 路并发时整体吞吐还能维持在 250 tokens/s 以上TTFT 稳定在 200-300ms 区间。对比一下FP16 基线在同样 24GB 卡上根本跑不动在 A100 上单路也只有 30 出头。到这一步优化目标全部达成单卡成本降下来延迟也满足交互场景。顺带说一句如果同样的流程换成 q4_k_m 的 GGUF 跑 llama.cppCPU 上也能有 5-10 tokens/s 的水平这给低端部署场景提供了很划算的选项。5. 常见问题与排查技巧实录5.1 量化后模型胡言乱语怎么办症状是压到 INT4 后输出变成乱码或驴头不对马嘴。排查有个固定顺序先在原 FP16 模型上跑同一批 prompt确认不是模型本身问题。接着检查校准集来源是否和业务数据分布差太多换混合校准集重跑。再检查 group_size从 128 切到 32 看质量是否恢复。然后看 desc_act关掉后如果明显变差说明模型对列排序敏感。都不行就换 AWQ 重跑AWQ 对 outlier 更友好。最后再用 LoRA 补偿微调拉质量。按照这个顺序走90% 的情况能定位到原因。5.2 显存占用不降反升量化完加载到显存占用比 FP16 还高这种事我遇到过。常见原因有三个加载时仍保留了 FP16 master weights某些库默认先加载原始权重再叠加量化权重KV cache 没有量化且序列很长多个推理框架同时加载同一模型。解法是检查模型 config 里的 torch_dtype 和 quantization 配置用 use_safetensors 正确加载必要时对 KV cache 启用 FP8 或 INT8 量化。排查顺序就是先看权重再看 KV cache最后看有没有重复加载。5.3 推理速度没有明显变快INT4 模型在高端 A100 上速度和 FP16 差不多甚至更慢这个也正常。INT4 的优势在于降低显存带宽需求但 GPU kernel 本身如果没有针对性优化尤其小 batch 场景下优势体现不出来。还有 desc_act 开启、不支持 INT4 的 kernel fallback 到 fp16 accumulate 等原因。解法很直接用 vLLM 或 TensorRT-LLM 而不是简单的 HF generate开启 FlashAttention确认 GPU 架构支持对应 kernel最后再用 profiling 工具看是否真的受带宽限制。优化要对着瓶颈做而不是对着参数做。5.4 校准集和评估集串台不少量化脚本默认用同一个数据集做校准和评估这等于考试前看答案评估结果虚高一上真实业务就露馅。我的做法是严格隔离校准集取 c4 前 2000 条评估集取 wikitext2 后 1000 条保证无重叠。这个原则同样适用于下游任务校准集里不要混入任务样本。看起来是个小原则但能避免大量虚假的优化效果反馈。5.5 量化格式与推理引擎不兼容工程上最容易翻车的是格式和版本不匹配。常见的有模型是用 auto-gptq 压的但 vLLM 版本只支持 gptq_marlin 格式AWQ 模型塞进只支持 GPTQ 的加速卡GGUF 的 group size 和 llama.cpp 编译参数不一致。我的排查法则是每一步转换都记录 quant_config.json部署环境里先跑一个 10 条样本的 smoke test不行就逐个环节回溯。另外transformers 和 auto-gptq/autoawq 的版本兼容矩阵一定要写进项目 README版本坑比功能坑多得多。5.6 补偿微调过拟合LoRA 补偿微调常见的失败模式是评估分数先升后跌。我一般把步数上限定在 1000 步每 200 步存一个 checkpoint 并跑一次 ppl 加任务评估取分数峰值对应的 checkpoint而不是最后一个。这个做法听起来简单但能避免大多数微调后反而更差的翻车。6. 实操心得与几个值得坚持的好习惯模型优化做了大半年最深的体会是先诊断再优化别急着上手压。拿到一个模型先 profiling 看瓶颈到底在显存、带宽还是算子再决定用哪套方案。如果显存够、带宽也够只是算子慢那你压量化还不如去调 kernel。诊断完再动手能省掉大量无效操作。我见过不少人一上来就 INT4最后发现瓶颈根本不在权重纯粹给自己加戏。另一个习惯是每步一个 checkpoint 和评估报告。优化过程里最怕的就是不知道哪个动作导致效果下降。我严格要求每个 Stage 落盘一个模型目录和一份 JSON 报告后续排查问题时拿报告一对比就知道是哪一步掉的分、掉的幅度多大。这个习惯看起来很笨但它让优化从手艺活变成了可复现的工程流程。版本锁死这件事值得单独强调一遍。CUDA、PyTorch、transformers、auto-gptq、autoawq、vllm 之间的兼容矩阵非常脆弱升级任何一个都可能让整套流程报废。我在项目里用了一个 requirements-lock.txt把所有关键依赖版本固定每次复现环境照着装半小时就能跑通。别相信最新版只相信验证过的版本。最后说说后续想做的事。Model-Optimizer 目前在往两个方向扩展一个是投机采样和动态批处理的调优让量化模型的解码速度进一步逼近带宽极限另一个是端侧小模型场景用蒸馏加量化组合把手持设备和 PC 端的部署体验做上来。模型优化不是一次性动作模型一升级流程要重跑业务数据一变校准集要更新。把优化沉淀成带评估闭环的流水线每一次改动都能度量、能回溯这件事本身就是最大的工程价值。
网站建设高端定制企业官网