vLLM AWQ 4-bit 量化实践:AutoAWQ 模型加载、推理配置与内核调度原理
2026/9/7 18:54:46 网站建设 项目流程

vLLM AWQ 4-bit 量化实践:AutoAWQ 模型加载、推理配置与内核调度原理

【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm

AWQ(Activation-aware Weight Quantization)通过把 BF16/FP16 权重压缩到 INT4,在几乎不损失精度的前提下显著降低模型显存占用,是 vLLM 中长期使用的低比特量化方案之一。本文围绕 vLLM 仓库中的 AutoAWQ 文档与实现展开:先讲如何用 AWQ 工具链产出 4-bit 量化模型并用 vLLM 加载推理,再深入 auto_awq.py 源码,剖析 vLLM 对 AWQ 检查点的位打包格式转换、Marlin/Triton 双内核调度以及 MoE 层回退机制,读完后可完整掌握 AWQ 量化模型在 vLLM 中的端到端使用与实现细节。

一、AWQ 在 vLLM 中的定位与当前推荐工作流

vLLM 的量化功能总览见 量化文档,其中 AWQ 是列明的受支持格式之一。需要先说明一个重要的状态变化:

AutoAWQ 这个独立量化工具库已被弃用,其量化能力已被 vLLM 项目吸收并迁移到llm-compressor中(对应 llm-compressor 的 AWQ 示例工作流)。对于新建的量化流程,仓库文档建议使用 llm-compressor 提供的 AWQ 示例;而vLLM 推理端对 AWQ 格式模型的加载与加速支持不受影响--quantization auto_awq依然是加载既有 AWQ 检查点的正式入口。

量化本身的原理不变:AWQ 将权重从 BF16/FP16 降低到 INT4,使模型总体内存占用下降,主要收益是更低的延迟和内存占用。你既可以自己量化模型,也可以直接选用 Hugging Face 上现成的 AWQ 模型(仓库文档提到量级为 6500+ 个)。

二、用 AWQ 工具链产出 4-bit 量化模型

以 AutoAWQ 为例(pip install autoawq安装),对mistralai/Mistral-7B-Instruct-v0.2进行 4-bit 量化的完整脚本如下,继承自文档 auto_awq.md:

from awq import AutoAWQForCausalLM from transformers import AutoTokenizer model_path = "mistralai/Mistral-7B-Instruct-v0.2" quant_path = "mistral-instruct-v0.2-awq" quant_config = {"zero_point": True, "q_group_size": 128, "w_bit": 4, "version": "GEMM"} # Load model model = AutoAWQForCausalLM.from_pretrained( model_path, low_cpu_mem_usage=True, use_cache=False, ) tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) # Quantize model.quantize(tokenizer, quant_config=quant_config) # Save quantized model model.save_quantized(quant_path) tokenizer.save_pretrained(quant_path) print(f'Model is quantized and saved at "{quant_path}"')

quant_config各字段与 vLLM 端的解析一一对应,这一点可以从 AutoAWQConfig.from_config 中得到印证:

字段示例值含义vLLM 侧解析
w_bit/bits4权重位宽,vLLM 仅接受 4(TYPE_MAP = {4: scalar_types.uint4}),8-bit AWQ 需走 Marlin 后端cls.get_from_keys(config, ["w_bit", "bits"])
q_group_size/group_size128分组量化粒度,-1表示逐通道(channel-wise),加载时归一化为input_sizecls.get_from_keys(config, ["q_group_size", "group_size"])
zero_pointTrue是否使用带零点的非对称量化;zero_point会影响 Marlin 内核支持性判断cls.get_from_keys(config, ["zero_point"])
lm_head缺省 False输出层(LM Head)是否也被量化get_from_keys_or(..., default=False)
modules_to_not_convert可选保持未量化的模块列表,加载时以子串匹配跳过并回退到UnquantizedLinearMethodget_from_keys_or(config, ["modules_to_not_convert"], None)
version"GEMM"AWQ 工具链侧的打包格式标记vLLM 侧不直接消费

此外,from_config 还会把完整配置复制一份并把quant_method强制改写为"awq"(存入full_config),原因是 MoE 层回退所用的MoeWNA16Config只接受"gptq""awq"两种取值——这是配置解析里容易被忽略的一个兼容细节。

AWQ 检查点的量化元信息存放在模型目录下的quantize_config.jsonquant_config.json中,由 get_config_filenames 声明。

三、用 vLLM 运行 AWQ 模型

3.1 命令行方式

文档给出的最简运行命令(使用 Hugging Face 上现成的TheBloke/Llama-2-7b-Chat-AWQ模型):

python examples/deployment/llm_engine_example.py \ --model TheBloke/Llama-2-7b-Chat-AWQ \ --quantization auto_awq

对应的示例脚本位于 examples/deployment/llm_engine_example.py。

3.2 LLM 离线推理入口

AWQ 模型同样可以直接通过LLM类加载:

from vllm import LLM, SamplingParams # Sample prompts. prompts = [ "Hello, my name is", "The president of the United States is", "The capital of France is", "The future of AI is", ] # Create a sampling params object. sampling_params = SamplingParams(temperature=0.8, top_p=0.95) # Create an LLM. llm = LLM(model="TheBloke/Llama-2-7b-Chat-AWQ", quantization="auto_awq") # Generate texts from the prompts. The output is a list of RequestOutput objects # that contain the prompt, generated text, and other information. outputs = llm.generate(prompts, sampling_params) # Print the outputs. for output in outputs: prompt = output.prompt generated_text = output.outputs[0].text print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

3.3--quantization参数到底接受哪些取值

从源码看,AWQ 家族在 vLLM 中的注册名并不只有一个。量化方法注册表 中把awqawq_marlinauto_awq三个名字统一映射到同一个AutoAWQConfig,因此这四个用户侧取值都可使用:auto_awqawqawq_marlin,以及显式指定marlin时也会命中 AWQ 检查点。

自动识别逻辑在 override_quantization_method:只要模型quant_configquant_method == "awq",且用户没有指定冲突的后端(用户量化参数为Noneawqawq_marlinauto_awqmarlin时均接受),vLLM 就会自动切换到auto_awq方法——也就是说,即使不传--quantization,vLLM 也会通过模型自带的量化配置自动识别 AWQ。CPU 平台是例外:该方法直接返回None,把处理权让给 CPU 专属的 AWQ 路径,避免覆盖冲突。这条 override 链路的顺序约束可以在 config/model.py 的 _verify_quantization 中看到,auto_awqawqawq_marlin都列在优先探测的覆盖方法名单中。

四、硬件兼容性

量化总览文档 给出的兼容性矩阵中,与 AWQ 直接相关的两行是:

实现VoltaTuringAmpereAdaHopperIntel GPU (XPU)x86 CPU
AWQ不支持支持支持支持支持支持支持
Marlin(GPTQ/AWQ/FP8/FP4)不支持支持(不支持 MXFP4)支持支持支持不支持不支持

这与源码一致:AutoAWQConfig.get_min_capability 返回75(即 Turing SM 7.5 起步),支持的活动 dtype 为torch.halftorch.bfloat16;而 CPU/XPU 上的 AWQ 走的是 WNA16 内核路径(见下文 5.2 节)。

五、vLLM 源码实现剖析

核心实现集中在 auto_awq.py。类注释明确说明:这是一个统一配置类,同时支持 Triton、Marlin 与 XPU 三种后端。

5.1 AWQ 非标准位打包与格式转换

AWQ 检查点有一个容易踩坑的特性:它的 int32 内部位打包顺序是非标准的。对于 4-bit 数据,常规顺序把值放在 bit 位[0,4,8,12,16,20,24,28]对应索引[0,1,2,3,4,5,6,7],而 AWQ 的排列是索引[0,4,1,5,2,6,3,7]。vLLM 用常量 _REVERSE_AWQ_PACK_ORDER = [0, 4, 1, 5, 2, 6, 3, 7] 记录这一逆序。

权重加载后,create_weights 仍按 AWQ 原始布局(qweight沿输出维打包、形状[K, N // pack_factor])创建PackedvLLMParameterpack_factor = 32 // 4 = 8;真正的大转换发生在加载完成后的 process_weights_after_loading 中,它调用 _convert_awq_to_standard_format:

  • 先把 int32 拆包成独立的 4-bit 值,并应用逆序排列纠正位顺序;
  • 再把qweight沿输入维重新打包为[K // 8, N]packed_dim=0),变成标准 GPTQ-like 布局;
  • qzeros同步做位序纠正与转置重打包为[N // 8, G]

从源码结构看,这一步是 AWQ 检查点能够无缝复用 GPTQ/Marlin 系内核的关键——内核只认标准布局,格式差异全部在权重预处理阶段消化。

5.2 线性层内核调度:Marlin 优先,Triton 兜底

AutoAWQConfig.get_quant_method 是分流中枢,对LinearBase层的决策顺序为:

  1. 跳过列表:若该层前缀命中modules_to_not_convert(子串匹配),返回UnquantizedLinearMethod按原精度计算。此外,maybe_update_config 会在配置未显式给出跳过列表时,扫描 safetensors 元数据,把 safetensors 里仍是 fp16/bf16/fp32 的层自动补进modules_to_not_convert——部分量化模型因此无需手工维护该列表。
  2. CPU / XPU:返回AutoAWQMarlinLinearMethod,但其内部通过choose_mp_linear_kernel实际选择的是 CPUWNA16 / XPU WNA16 内核,而非 GPU Marlin。
  3. CUDA 且 Marlin 可用:条件为未开启VLLM_BATCH_INVARIANT、且check_marlin_supported(quant_type, group_size, zero_point)通过;再逐层校验check_marlin_supports_layer(allow_tile_padding=True),个别不满足的层会打 warning 并单独回退到 Triton 的AutoAWQLinearMethod
  4. 其余情况:直接使用AutoAWQLinearMethod(Triton/自研 CUDA 内核)。

AutoAWQMarlinLinearMethod通过MPLinearLayerConfig描述完整权重形状、分区形状、uint4权重类型、活动 dtype、group_sizezero_points,再交给choose_mp_linear_kernel挑选当前平台上最优内核(Marlin/ExLlama/Conch 系),并在日志中记录实际使用的内核类型。

5.3 Triton 路径的运行时分支

AutoAWQLinearMethod.apply 里有一个值得注意的启发式:

FP16_MATMUL_HEURISTIC_CONDITION = x.shape[:-1].numel() >= 256 if FP16_MATMUL_HEURISTIC_CONDITION or envs.VLLM_BATCH_INVARIANT: out = ops.awq_dequantize(qweight, scales, qzeros, 0, 0, 0) out = torch.matmul(reshaped_x, out) else: out = ops.awq_gemm(reshaped_x, qweight, scales, qzeros, pack_factor)
  • token 数 ≥ 256(大 batch / prefill 场景)时,先整体反量化为 FP16 矩阵再做torch.matmul,利用高算力场景下 TensorCore 的吞吐;
  • 小 batch(decode 场景)时,走融合反量化 + 矩阵乘的awq_gemm内核,避免显式展开权重的额外访存;
  • 开启VLLM_BATCH_INVARIANT(批不变模式,用于确定性推理)时强制走 matmul 路径,因为该模式要求 Triton 可覆盖的torch.matmul语义。

底层入口在 _custom_ops.py 的 awq_dequantize / awq_gemm:当环境变量VLLM_USE_TRITON_AWQ开启时,二者分别委托给 awq_triton.py 中的纯 Triton 实现,否则调用编译好的 C++/CUDA 算子torch.ops._C.awq_dequantize/torch.ops._C.awq_gemm。Triton 实现的关键约束(来自 awq_triton.py):

  • 支持的group_size[-1, 32, 64, 128]-1即逐通道,或等于K本身);
  • awq_gemm_tritonsplit_k_iters必须是 2 的幂且不超过 32,用于沿 K 维切分并行;
  • 两个内核都内置了reverse_awq_order_tensor(即[0,4,1,5,2,6,3,7]的逆序展开),在tl.dot累加前完成b = (b >> shifts) & 0xFzeros = (zeros >> shifts) & 0xFb = (b - zeros) * scales的反量化,与 5.1 节描述的位序问题完全对应。

5.4 MoE 专家层的 AWQ 支持

RoutedExperts(MoE 路由专家层),get_quant_method 会优先尝试 AutoAWQMoEMethod:

  • 目前仅支持 4-bit(weight_bits != 4直接抛错);
  • 通过select_wna16_moe_backend选择 WNA16 MoE 后端(含 Humming 等特殊后端分支),加载完成后由convert_to_wna16_moe_kernel_formatw13_qweight/w2_qweight/ scales / qzeros 转换为模块化内核所需的布局;
  • 若某层不满足 MoE Marlin 形状要求,则回退到通用的MoeWNA16Config(这正是full_config里强制quant_method="awq"的原因),并记录 warning。

六、测试与验证依据

仓库自带针对 AWQ 统一化改造的测试 tests/quantization/test_auto_awq.py,覆盖四类场景:from_config对各字段(w_bit/bitsq_group_size等)的解析与异常(不支持的位宽抛错)、pack_factor == 8的属性一致性、CPU 平台 override 冲突(override_quantization_method必须检测is_cpu()并返回None),以及端到端加载——以Qwen/Qwen2-1.5B-Instruct-AWQ为小模型,通过is_quant_method_supported("auto_awq")按 GPU 能力自动跳过不支持的硬件。可以在本地按相同方式构造一个最小 AWQ 检查点来验证自己的量化流水线是否与 vLLM 的加载假设一致。

七、小结

  • 产出模型:AutoAWQ 工具链已弃用、量化工作流推荐迁移到 llm-compressor 的 AWQ 示例;但既有的w_bit=4q_group_size=128zero_point=True检查点格式 vLLM 完全兼容。
  • 加载推理--quantization auto_awq等价于awq/awq_marlin/marlin,四者都注册到同一个AutoAWQConfig;不传该参数时 vLLM 也会依据模型内嵌quant_config自动识别。
  • 内核策略:GPU 上 Marlin 优先、Triton 兜底,CPU/XPU 走 WNA16 内核;Triton 路径按 token 数 256 在融合 GEMM 与"反量化 + matmul"之间切换,VLLM_BATCH_INVARIANT可强制确定性路径。
  • 格式要点:AWQ 的[0,4,1,5,2,6,3,7]位序与沿输出维的打包布局,在process_weights_after_loading阶段统一转换为标准 GPTQ-like 格式,这是理解 AWQ 内核与 GPTQ 内核共享同一套基础设施的关键。

【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询