HyperQwen int8 张量核实战修复 Marlin W4A8 负缩放 bug 并逐层选择激活量化【免费下载链接】HyperQwenServe large Qwen models fast on the GPUs you actually own. Qwen3.8-27B on a single 24 GB card with vLLM: 127 tok/s single-user (381 when the answer quotes the prompt), ~1,035 tok/s at 64 concurrent, 150k-262k context. vLLM patches, requant pipeline, benchmarks.项目地址: https://gitcode.com/gh_mirrors/qw/HyperQwenHyperQwen 是一个让消费级显卡快速服务大 Qwen 模型的项目它在单张 24 GB 显卡上用 vLLM 跑 Qwen3.8-27B单用户 127 tok/s、64 并发下约 1,035 tok/s。本文聚焦它量化链路中最坑的一环——int8 激活量化W4A8vLLM 的 Marlin W4A8 内核在这份检查点上会静默输出乱码负组缩放被当成无符号数读取HyperQwen 用一个加载期补丁修复了它再配合逐层正则选择决定哪些线性层真正走 int8 张量核。下面按为什么要做 → 坑在哪 → 如何核实 → 如何逐层选择的顺序展开。为什么 int8 激活量化W4A8值得做 高并发解码时瓶颈在 fp16 张量核矩阵乘250 W 功耗上限下约 63 TFLOPS 持续算力。vLLM 已经内置一条W4A8-INT8 Marlin 路径权重保持 int4激活按 token 量化成 int8矩阵乘改在 int8 张量核上以约 4 倍速率执行。在批量模式batch mode下这一步的实测收益是累积式的关键台阶累积步骤64 并发 e2e (tok/s)W4A16 基础量化 int8 嵌入矩阵516 fp16 循环状态707 int8 激活仅 MLP942 int8 激活所有线性层1,042单用户模式下 prefill 同样受益4k 输入时从 1,437 提升到1,937 tok/s35%且解码速度不变。完整数据见 docs/optimizations.md。但快 4 倍的前提是这条路真的算对了——这正是下面的故事。隐藏的地雷负组缩放 bug 症状很诡异输出是乱码但跑分很好看。根因在 Marlin 内核的读取方式int8 激活路径会把 fp16 组缩放重新量化为 int16 存下而 CUDA 内核marlin_template.h中的reinterpret_castuint16_t*随后把它们按无符号 int16解读。问题是AutoRound 对称量化导出的检查点里大约50% 的组缩放是负数——每个负缩放组经无符号解读后都变成巨大的错误数值整组权重全部失真。修复思路很巧与其改内核不如在加载时把符号折叠进 int4 码缩放 s → -s码 q → -q即uint4b8码 v → 16 - v。数学上与原值等价唯一的极小代价是翻转组里罕见的码值 -8 会差一个最低位16 - 8 需要钳到 15。整个修复逻辑集中在 patches/marlin-int8-negative-scales.patch 中加载阶段的这段处理_neg _ws.data 0 # 找出负缩放组 _nib torch.where(_neg_rows.unsqueeze(-1), _flip, _nib) # 对翻转组的 int4 码取补 _ws.data torch.where(_neg, -_ws.data, _ws.data) # 缩放取正这段代码在权重重排permute之后执行只在检测到负缩放时才触发对没有负缩量的检查点零开销。int8 张量核实战数值验证怎么做 修完 bug 不能只靠看起来正常了。HyperQwen 的做法是逐形状数值核实1. 构造受控的量化权重对比 float 参考。bench/test_marlin_int8_asym.py 按本模型的真实矩阵形状5120×17408、17408×5120 等构造随机非对称 int4 g128 权重走 compressed-tensors 的打包布局然后对同一组打包权重分别跑 bf16 激活和 int8 激活两条 Marlin 路径与反量化权重的 float 参考矩阵乘对比相对误差。验收标准是int8 路径在所有形状上相对误差 5%实测在 RTX 3090 上为0.9%~1.05%W4A16 路径为 0.26%——这个差值正是 int8 激活本身引入的噪声与对称/非对称无关。2. 补齐非对称带零值权重的支持。带零值的uint4权重AWQ 非对称导出此前会在process_weights_after_loading阶段被两条断言拒之门外AssertionError: W8A8 is not supported by marlin kernel。实际上kS8 x kU4AWQ 零值权重 int8 激活的内核早已编译好了只是断言只放行了uint4b8。patches/marlin-int8-asym-zp.patch 把两处断言改为同时接受uint4让非对称导出也能跑 W4A88 位权重真正的 W8A8依旧被拒绝——那是确实没有内核的情况。3. 质量兜底。逐层核实之外docs/quality.md 给出了整栈配置下的 IFBench、困惑度和 GSM8Kint8 激活的默认配置整 MLP相比 W4A16困惑度约 2.2%主要落在代码上GSM8K 95.0% vs 95.5%IFBench 持平——量化换来的吞吐是有据可查的不是玄学。逐层选择激活量化哪些层走 W4A8 默认行为是一刀切设置VLLM_MARLIN_INPUT_DTYPEint8后vLLM 会给每一个Marlin 层开 int8 激活。这在这份检查点上有两个问题lm_head 是 int8 权重的W8A8Marlin 内核不支持一刀切会直接拒绝加载吞吐与质量没有权衡空间——不同层类型对 int8 噪声的敏感度不同应该能按层取舍。patches/marlin-int8-layer-select.patch 为此增加了两个环境变量按层名做正则匹配环境变量默认值含义VLLM_MARLIN_INT8_EXCLUDE_RElm_head\|mtp命中则不走 int8 激活VLLM_MARLIN_INT8_INCLUDE_RE空 全部命中才走 int8 激活这两个变量被显式注册进 vLLM 的envs.py以参与 torch.compile 缓存键——否则切换层选择后旧的编译图会被重放直接崩在KeyError: input_global_scale补丁头部注释里写明了这个坑。对普通用户来说不用直接碰这些底层变量启动脚本已经把它们包成了更直观的开关。批量模式默认INT8_ACTint8int8 张量核算 MLP 的 GEMM单用户模式可用INT8_ACTint8提升 prefill具体见 single-user/README.md 与 batch/README.mdINT8_LAYERSgate_up—— 温和档只动 gate/up 投影困惑度 0.9%INT8_LAYERSmlp默认—— 吞吐与质量的折中点困惑度 2.2%INT8_LAYERS.—— 所有线性层全开64 并发下吞吐再上一档但批量模式需要GPU_UTIL0.95才放得下瞬时缓冲一句话总结取舍批量模式默认全开 MLP 档吃吞吐质量敏感场景退到gate_up单用户模式把 int8 留给 prefill。上手建议与延伸阅读 如果你在自己的 vLLM 环境里遇到W4A8 跑分正常但输出胡说八道大概率就是负缩放问题可以按这个顺序排查确认你的量化导出方式——AutoRound 对称导出的检查点中招概率最高约一半组缩放为负加载期检查缩放张量存在scale 0就必须先做符号折叠参照 patches/marlin-int8-negative-scales.patch 的做法用 bench/test_marlin_int8_asym.py 的思路做逐形状数值核实把 int8 路径与 float 参考的相对误差控制在个位数百分比用正则把 W8A8 层int8 权重层和草稿模块排除在 int8 激活之外再按层调吞吐/质量档位。所有补丁的来龙去脉类型、上游对应、何时退役收录在 PATCHES.md 的补丁清单里本文涉及的三行是marlin-int8-negative-scalesfix—— W4A8 负组缩放等上游合并marlin-int8-layer-selectlocal—— 逐层正则选择长期保留marlin-int8-asym-zpfix—— 零值uint4权重的 int8 激活支持想深挖每一步优化值多少 tok/s 的完整推导读 docs/optimizations.md想知道 int8 到底花了多少质量看 docs/quality.md。【免费下载链接】HyperQwenServe large Qwen models fast on the GPUs you actually own. Qwen3.8-27B on a single 24 GB card with vLLM: 127 tok/s single-user (381 when the answer quotes the prompt), ~1,035 tok/s at 64 concurrent, 150k-262k context. vLLM patches, requant pipeline, benchmarks.项目地址: https://gitcode.com/gh_mirrors/qw/HyperQwen创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考