本記事にはアフィリエイト広告(Amazon アソシエイト)が含まれます。
実測日: Tue Jun 02 2026 09:00:00 GMT+0900 (Japan Standard Time)
INT8 に量子化した Qwen3.5-9B を、Qualcomm の対話ランタイム Genie で動かした。 一発実行の数字(前々回)や converter の格闘(前回)と違い、ここでは実際に token が順に出てくる。 本記事は、基本の対話が通った構成と、その先で試した投機的デコード(Speculative Decoding、以下 SSD)とスパース演算の結果をまとめる。
4 層ずつ 8 段に分ける
9B のグラフを 1 つの context に収めず、4 層ずつ 8 段の context binary に分けた。
この構成で DLC と .bin を作り、Genie の基本の対話は完了扱いにした。
以後の試験は、この構成を壊さないことを条件に進めた。
Qwen3.5 が Genie にとって扱いにくいのは、通常の attention の KV cache と、線形 attention(DeltaNet)の再帰状態を同時に持つからである。 純粋な Transformer より状態の種類が多く、ランタイムが前提にする入力面と食い違いやすい。 この食い違いが、次の SSD で表に出た。
投機的デコードは 2 token までは動く
Genie の SSD は、draft が提案した候補を target が検証する仕組みで、候補の選択 mask を KV cache の管理器に渡す。 最小の設定(候補 1、分岐 1)で、生成する token 数だけを変えて測った。
| 生成 token 数 | 結果 | TTFT | 生成速度 |
|---|---|---|---|
| 2 | 成功 | 907 ms | 1.10 tok/s |
| 3 | KV 更新で失敗 | 909 ms | 途中で停止 |
| 4 | KV 更新で失敗 | 910 ms | 途中で停止 |
2 token は 1 号機と 2 号機の両方で再現し、致命的なエラー無しで終わる。 3 token 以上では、次のエラーで止まる。
Invalid selection mask size. Found 4 but expected 0 or 23setupInput : Missing token history. Expected 19, Found ...Genie のソースを追うと、KV の管理器は選択 mask の長さが処理長 n_process と一致しないとエラーにし、処理長は mask の長さに 19 を足した値になっていた。
19 は、現在の 4 層 × 8 段の入力面が期待する token 履歴の長さである。
つまり、SSD が作る候補 mask の長さと、context binary が受け取る入力面の設計が合っていない。
設定を増やしても解決しないので、次の工程は入力面の再設計になる。
途中で試して採用しなかった構成も残しておく。
下流の shard から input_ids を外して context を小さくする案と、graph を持ち替える設定を有効にする案は、どちらも I/O テンソルが見つからず起動しなかった。
位置情報の position_ids_sin と position_ids_cos が見つからない問題は、位置符号化の種類を absolute にして回避できた。
1.10 tok/s をどう読むか
2 token の試験で出た 1.10 tok/s は、速度の評価値として採用しない。 生成が 2 token だけで短すぎること、draft を使った本来の投機ではなく配線の確認であること、が理由である。 Genie が KV cache の管理を通して decode に入っている、という事実の確認までが、この数字の意味である。
それでも、音声応答の裏側に 9B をそのまま置くには遅い、という感触は得られた。 9B を target とする正しい decode の基準は保ちつつ、Qwen3.5 0.8B のような小型の draft を別に用意する方向に決めた。
スパース演算は HTP で準備できない
INT8 の疎な行列を HTP で直接扱えないか、C API で確かめた。
| 確認 | 1 号機 | 2 号機 |
|---|---|---|
| backend の sparsity capability | supported | supported |
CreateSparse と SparseToDense の対象 |
CPU | CPU |
| HTP での graph finalize | エラー 1002 | エラー 1002 |
capability は supported と返るのに、実際に graph を組むと no properties registered for q::CreateSparse.tmp で finalize が落ちる。
対応表では両演算の対象が CPU になっており、この SDK と backend の組み合わせでは HTP 向けに準備できないと判断した。
ONNX の疎な initializer を使う経路も、converter が KeyError: 'W' で止まった。
当面、疎化は構造化した零を持つ dense の成果物で比較を続け、HTP の疎演算は検証枝として残す。
到達点
- INT8 dense の 4 層 × 8 段で、Genie の基本の対話は動く。
- SSD は 2 token の配線確認まで。3 token 以上は入力面の再設計が要る。
- HTP の疎演算は capability と実際の準備が一致しない。
- 音声の裏側に使うには、9B の decode は遅く、小型の draft が要る。
一発実行の 1,000 tokens/sec から始めて、実際の decode の壁まで辿り着いた。 数字の意味を取り違えないために、どの区間を測ったかを毎回書き残しておく。
この記事で扱った機材
Crucial DDR5-5600 SO-DIMM 128 GB キット(64 GB × 2、CT2K64G56C46S5)
27B 級の重みを bf16 のまま読み込んだり、1 bit への変換の中間状態を持ったりするには、ミニ PC のメモリをこの容量まで積む必要がある。