Intel B60 的量化模型与优化路径兼容性
量化模型在 XPU 上能够加载,不代表生成路径与所有优化组合都正确。Qwen3.5-9B 在单张 Intel Arc Pro B60 上的测试中,旧镜像曾产生无关回答和非法 JSON;升级后又出现量化层字段与 GDN 输出投影优化不兼容的问题。同样是低比特权重,GPTQ 与 AutoRound 模型包的表现也并不一致。
因此版本升级需要同时验证加载、首请求、图文生成、结构化输出和重复请求,不能仅以服务返回 health 200 判定完成。
设备检查、容器启动、接口调用与并发测试的基本流程,见 Intel B60 上的 Qwen3-VL vLLM 部署;具体模型包和镜像仍按本篇组合单独验证。
一、量化表示与实际执行
量化兼容性至少涉及三件事:模型包怎样存储权重,加载器把它转换成什么层,以及推理时最终选择哪个 kernel。模型名里的 GPTQ 或 INT4 只说明了其中一部分。旧镜像虽然以 --quantization gptq 启动,日志最终解析出的执行配置却是 quantization=ipex;另一个 AutoRound 模型包使用 GPTQ 风格的打包格式,运行时则识别为 inc。不能只凭文件名判断两者会走相同的执行路径。
GPTQ 权重常以 qweight、qzeros、scales 保存,其中包含打包后的整数与分组量化参数,未必存在普通浮点 Linear 的 weight。Qwen3.5 又同时包含 Gated DeltaNet(GDN)线性注意力与全注意力层,除了通用矩阵乘,还会进入模型专用的优化路径。这里遇到的错误发生在 GDN 输出投影:
AttributeError: 'RowParallelLinear' object has no attribute 'weight'Intel 仓库的 issue #533 和 PR #557 描述了相同的故障机制:ESIMD 输出投影的资格检查直接读取 self.out_proj.weight。本应先判断该层能否使用优化,却在判断过程中就因字段缺失退出。因此,权重加载和缓存分配都可以完成,首次请求执行到这一层时才会崩溃。
修复提案将直接访问改为 getattr,让缺少浮点权重的层回退到通用输出投影。关键是保留量化层自己的执行入口,不能把 qweight 直接当作浮点 weight 替换进去:前者还需要结合尺度、零点与打包布局才能解释。
归档 intel/llm-scaler-vllm:0.21.0-b3 中,设置以下开关绕过了有冲突的检查,保留通用输出投影路径:
export DISABLE_ESIMD_GDN_OUTPROJ=1单 B60、TP=1、GPTQ 权重、FP16 计算、FP8 KV 和 eager 的组合随后通过了普通问答、图文问答、JSON 与重复请求的串行回归。这个结果尚未覆盖长时间运行和混合并发,也不代表该镜像已经完整支持所有 GPTQ 模型。开关只绕过这条 GDN 优化路径,不会关闭全部 XPU 加速;后续版本是否仍需要它,应按实际代码和回归结果判断。
二、分开评估优化项
| 项目 | 主要改变 | 验证内容 |
|---|---|---|
| 权重量化 | Linear 表示与 kernel | 生成内容、视觉与 JSON |
| FP8 KV | 缓存容量与读写 | 长上下文数值与容量 |
| XPU graph | 捕获与执行路径 | 首请求、重复请求、shape |
| GDN 优化 | 线性注意力实现 | dtype、权重接口与数值 |
FP8 KV 可以提升可用 token 容量,但容量提升倍率受权重、缓存预留和实现影响,不能直接解释为等倍率吞吐改善。eager 基线通过后再启用 graph,便于定位新故障。
这里尤其容易混淆的是 dtype。INT4 描述权重存储,FP16/BF16 描述计算张量的类型,FP8 KV 描述注意力缓存的存储类型。设置 --kv-cache-dtype fp8,不会自动把 query 或其他中间张量变成 FP16;FP16 和 BF16 虽然都占两字节,内核也不能直接混用。
AutoRound 对照测试中,XPU graph 已完成编译与捕获,首次真实推理仍出现以下断言:
Expected query.scalar_type() == torch::kHalf to be true, but got false这条日志能确定所选内核要求 FP16 query,而当时传入的类型不满足要求。结合 BF16 配置,可以定位到调用方与内核的类型约定不一致;仅凭它还不能认定 graph 本身不可用。图捕获成功也没有覆盖所有真实请求的执行条件。
三、相近的量化格式为何结果不同
AutoRound 对照模型的配置包含:
quant_method = auto-round
packing_format = auto_round:auto_gptq
bits = 4
group_size = 128auto_gptq 表示打包格式,量化方法仍是 AutoRound。分组方式、对称性、量化层范围和运行时转换都参与最终计算,不能因为权重也是四位、字段名相近,就强制套用另一个模型包的加载配置。部署时需要同时核对模型元数据和日志中实际选择的量化后端。
这一组测试也说明,消除异常只是第一步:
| 配置变化 | 实际现象 | 能确定的问题 |
|---|---|---|
| 未关闭 GDN 输出投影优化 | 首请求缺少 weight 字段 | 优化检查不兼容量化层接口 |
| 关闭该优化,eager+FP8 KV | 能生成,但文本和 JSON 仍异常 | 字段冲突已绕过,生成正确性仍未通过 |
| 关闭该优化,eager+auto KV | 首请求出现 BF16 KV 相关错误 | 自动选择的缓存类型不被当时执行路径接受 |
| 关闭该优化,启用 XPU graph | 捕获成功,真实推理出现 query 类型断言 | 所选内核与输入 dtype 不匹配 |
模型分片已完成完整性检查,降低了下载残缺的可能,但没有逐层数值对比,仍无法确定生成异常发生在权重解释、量化计算还是后续状态更新中。这只能说明该模型包与当时配置没有通过回归,不能推广成 AutoRound 方法本身有问题。
四、版本差异与生成异常
Intel 发布记录中,0.14.0-b8.3.2 明确列出了 Qwen3.5/3.6-27B 的精度修复,但它不是这里测试的 9B 模型,不能直接当作同一故障的修复证明。旧服务重启或调整参数后也曾短暂通过,版本、参数与运行状态的影响尚未完全分离。
因此目前能确认的是,固定的新组合在已记录的回归中没有复现原问题。若要继续追到数值原因,需要固定模型包、输入与生成参数,在相同精度下比较浮点和量化路径,再缩小到首次出现明显差异的层或 token。仅更换镜像后恢复正常,还不足以指出是哪一个 kernel 修好了问题。
五、建立最小回归集
先用自然语言描述确认视觉输入有效,再用同一张图片要求结构化结果;如果前者正确而后者失败,应分别检查语言生成、量化执行与格式约束,不把问题一概归到图片下载。
回归集可以固定短数学题、普通问答、单图描述、图文 JSON 和重复请求,另外加入首次请求、容器重启后的请求与长上下文。保存原始输出、退出状态和 OOM 标记,而非只保存解析后的 hit。
升级时从 eager 与已知模型开始,再逐项恢复 FP8 KV、graph 和其他优化。若同时换模型包、镜像与全部参数,成功只能说明新组合可用,无法判断旧故障究竟由哪一项消除。
结构化输出的校验与评测分层见 Qwen 小模型的结构化输出与任务评测,可用于区分格式约束未生效和模型判断本身异常。
六、一些反思
这次最值得注意的是,故障出在优化资格检查,而不是矩阵乘本身。通用 Linear 原本可以处理的量化层,可能因为新增的快速路径提前读取内部字段而无法执行。优化需要同时检查权重表示、dtype 和形状,并在条件不满足时保留可用的回退路径。
排查时也应区分三种情况:字段缺失可以沿调用栈定位接口假设,dtype 断言可以核对张量与内核约定,生成内容异常则需要数值对照。把它们都概括为“量化不兼容”,会掩盖已经确定的原因,也容易把尚未定位的问题说得过满。
接口回归也应包含输出语义。重复换行、无关内容和 JSON 合法性都可以在进程不退出时出现;服务可达只是最外层检查。