本記事にはアフィリエイト広告(Amazon アソシエイト)が含まれます。
実測日: Thu May 28 2026 09:00:00 GMT+0900 (Japan Standard Time)
前回、Qwen3.5-9B を FP16 と FP32 で Hexagon NPU(HTP)に載せた。 次は INT8 である。 重みの読み出しが半分になれば decode は速くなるはずだが、量子化は変換器の中で落ちた。 本記事は、その落ち方と、回避に至るまでの試行を記録する。
対象の大きさ
ONNX を静的に走査すると、量子化の候補になる演算の規模が見える。
| 項目 | 数 |
|---|---|
| Add 系の候補 | 6,393 |
| Mul 系の候補 | 8,377 |
| 層 0 の密度 | Add 264、Mul 344 |
| 層 31 の密度 | Add 7、Mul 15 |
層ごとの密度が大きく違うので、問題を探すときは層と枝の分布で優先順位を付けた。 変換を 1 回流すと、診断だけの短い経路で平均 140 秒、本番相当で平均 517 秒かかる。 当てずっぽうの再実行は時間を失うだけなので、走査を先に固定した。
signal 11 で落ちる
量子化の本線は、converter の量子化器が encoding(各テンソルの scale と zero point)を当てはめる apply_encodings() の途中で、signal 11 で異常終了した。
止まる場所は特定の Expand の直後で、再現性があった。
まず、encoding の当てはめを飛ばす診断用の経路を用意し、保存までの道が通ることを確かめた。 ただしこの回避は診断専用で、成果物に昇格させないことを決めた。 量子化していないものを INT8 と呼ぶわけにはいかない。
encoding を自前で作る
原因は、converter が内部で作る encoding が足りないテンソルがあり、そこで量子化器が落ちることだった。 そこで、encoding を外から与える方針に変えた。 これが 15 回の作り直しになった。
| 版 | 変えたこと | 結果 |
|---|---|---|
| v1 から v6 | FP16 のテンソルと _pre_reshape を除外 |
weight の y_scale が無いと言われる |
| v7 から v10 | weight の入力テンソルを追加 | 同上 |
| v11 | 形式を辞書からリストへ | name が無いと言われる |
| v12 から v13 | name を追加 |
y_scale が無いと言われる |
| v14 | すべての float32 を INT8 に | FP16 のテンソルは量子化できないと言われる |
| v15 | FP16 のテンソルを除外 | 別の FP16 テンソルで同じ指摘 |
v15 と --float_bitwidth 32 |
float32 で統一 | apply_encodings() を通過 |
判ったことは 3 つある。
- encoding の形式は版 2.0.0 で、リスト形式で各要素に
nameとy_scaleが要る。 - FP16 のテンソルには INT8 の encoding を当てられない。
既定の
--float_bitwidth 16だと converter が float32 を内部で float16 に変えるため、どこかで必ず衝突する。 明示的に 32 を指定すると、この衝突が消える。 - converter が reshape の前に作る
_pre_reshapeという内部テンソルが 3,359 個あり、親テンソルの encoding を引き継ごうとする。 除外しても別の経路で同じ指摘が出るので、FP16 を避ける側で解決するしかなかった。
通った後に残ったもの
最終版は 21,400 個の encoding を当てはめて apply_encodings() を通過した。
signal 11 は消え、量子化の上書き機構が働くことも確かめた。
その先で、backend の検証が止めた。
validateQnnOpConfig: Failed QNN validation for/wrapped_model/model/layers.3/self_attn/ExpandTensor 3962 and 3963 have mismatching datatypes. 0x232 != 0x216.これは encoding とは別の、型の不整合である。 同種の不整合は FP16 の変換で既に直した経験があり、同じ修正で対処できる見込みだった。 進捗で言えば、量子化の本線は 99.99% から 99.995% に進んだ。 残りは型の修正と、実際の精度の確認、そして Q900 の実機での実行である。
次の 9B のために残すこと
Qwen3.5 で確定した修正は、次の 9B 系モデルでも使い回せる形にした。 ONNX の静的走査を先に固定すること、encoding の網羅を実行前に検査すること、診断用の回避を成果物にしないこと、の 3 つである。 初回の安定化までの時間を、何も無い状態から始めるより 2 割から 4 割縮めることを狙っている。
この記事で扱った機材
Crucial DDR5-5600 SO-DIMM 128 GB キット(64 GB × 2、CT2K64G56C46S5)
27B 級の重みを bf16 のまま読み込んだり、1 bit への変換の中間状態を持ったりするには、ミニ PC のメモリをこの容量まで積む必要がある。