[cupel] M5 Max 128GB: Qwen3.5-397B IQ2 @ 29 tokens per second

Reddit r/LocalLLaMA / 2026/4/13

💬 オピニオンDeveloper Stack & InfrastructureTools & Practical UsageModels & Research

要点

  • 当該投稿では、非常に大規模なQwen3.5-397Bモデルを、M5 Max 128GBのMacBook上でローカル実行できるようになったと主張しており、その実現方法として、Unslothの「モデルごとの適応的な層量子化」と、「重要度マトリクス(imatrix)」アプローチの組み合わせが挙げられている。
  • 著者は、より小さなQwenモデルから段階的に構築していく手順を説明し、さらにコミュニティからのフィードバックをGemmaで整理したうえで、GitHub上のトラッキング付きの課題(issue)一覧へとまとめ上げた経緯を述べている。
  • 著者は、Unslothの「UD」量子化バリアント(例:Qwen3.5-397B-A17B-UD-IQ2_XXS)であることを具体的にテストし、異なる層に対して異なる量子化レベルが適用され、最も重要な層は損失や誤差を抑えるために丸め(四捨五入)されると説明している。
  • 実用的な計測結果として、モデルファイルの想定サイズと、実際にディスク上に出る総サイズの比較が示されている。あわせて、(ll/gguf-dumpといった)コマンド列によって、GGUFファイル内で使われている量子化レシピを調べる方法も提示されている。
  • 作成された量子化モデルはディスク上で約~106GBに到達したと報告されており、テンソルごとの量子化ビット幅と役割の検査、ならびに当該構成でのスループットが約~29 tokens per secondであるという報告も合わせて示されている。
[cupel] M5 Max 128GB: Qwen3.5-397B IQ2 @ 29 tokens per second

1年前なら、397Bのモデル群について読むだけでした。けれど今日では、ノートPCでそれを動かせます。重要度マトリクス(imatrix)と、Unslothの「モデルごとの適応型レイヤ量子化」を組み合わせたことが、これを可能にしている理由です。とはいえ、私が最初に397Bから始めたわけではありません。もっと小さい17個のモデルから始めました。

M5 Max 128GB, 17 models, 23 prompts: Qwen 3.5 122B is still a local king"」という議論からは、非常に多くの素晴らしいフィードバックがありました。

私はGemma 4で、すべてのフィードバックをアクションに整理し、Gemmaと一緒に、そのフィードバックと要望に対応するために取り組む作業リストを作りました: https://github.com/tolitius/cupel/issues/1

要望の1つは、「Qwen3.5-397B-A17B-UD-IQ2_XXS」をM5 Max 128GのMacBookでちょっと試してみることでした。これらのUnsloth(UD)モデルは本当に面白いです。なぜなら、異なる層がそれぞれ異なる形で量子化されるからです。最重要の(「I」)重みは、損失/誤差を最小化するように丸められます。

Qwen 397Bをダウンロードしたあと、何より先に、自分のノートPCに飲み込ませようとしているものが一体何なのか理解したくて確認しました:

$ ll -h ~/.llama.cpp/models/Qwen3.5-397B-A17B-UD-IQ2_XXS/UD-IQ2_XXS total 224361224 -rw-r--r-- 1 user staff 10M Apr 12 18:50 Qwen3.5-397B-A17B-UD-IQ2_XXS-00001-of-00004.gguf -rw-r--r-- 1 user staff 46G Apr 12 20:12 Qwen3.5-397B-A17B-UD-IQ2_XXS-00003-of-00004.gguf -rw-r--r-- 1 user staff 14G Apr 12 20:57 Qwen3.5-397B-A17B-UD-IQ2_XXS-00004-of-00004.gguf -rw-r--r-- 1 user staff 46G Apr 12 21:12 Qwen3.5-397B-A17B-UD-IQ2_XXS-00002-of-00004.gguf 

これで106GBだと分かりました。元の16bitモデルは807GBです。もし「単に」2bitに量子化するだけなら、(397B * 2 bits) / 8 = ~99 GB になるはずです。けれど実際は106GB。そこで、Unslothチームが実際に採用した量子化レシピをのぞき込んで確認したくなりました:

$ gguf-dump \	 ~/.llama.cpp/models/Qwen3.5-397B-A17B-UD-IQ2_XXS/UD-IQ2_XXS/Qwen3.5-397B-A17B-UD-IQ2_XXS-00002-of-00004.gguf \	 2>&1 | head -200 
Tensor type Quant Bits Role
ffn_gate_exps IQ2_XXS ~2.06 512 routed experts gate(モデルの大部分)
ffn_up_exps IQ2_XXS ~2.06 512 routed experts up(モデルの大部分)
ffn_down_exps IQ2_S ~2.31 512 routed experts down(もう1段上)
ffn_gate_shexp Q5_K 5.5 共有エキスパートゲート
ffn_up_shexp Q5_K 5.5 共有エキスパート up
ffn_down_shexp Q6_K 6.56 共有エキスパート down
attn_gate / attn_qkv Q5_K 5.5 GatedDeltaNet attention(linear attn layers)
attn_q / attn_k / attn_v / attn_output Q5_K 5.5 フル attention layers(4番目ごと)
ssm_out Q6_K 6.56 GatedDeltaNet 出力(最も感度が高い)
ssm_alpha / ssm_beta Q8_0 8.0 GatedDeltaNet gates
ssm_conv1d / ssm_a / ssm_dt / ssm_norm F32 32 小さなテンソルで、フル精度のまま保持
ffn_gate_inp (router) F32 32 MoE router weights
token_embd / output Q4_K 4.5 埋め込みとlm_head
norms F32 32 すべての正規化重み

超おもしろいです。エキスパートのテンソル(ffn_gate_expsffn_up_expsffn_down_exps)は約2ビットで量子化されていますが、残りはかなり大きい(ビット数が多い)。ここでの7GBの差(99GB vs. 106GB)が効いてきます:エキスパートのテンソルの上に、7GB分の“詰め込まれた知性”が載っているわけです。

火中の試練

試行錯誤の結果、128GBのユニファイドメモリに対するコンテキストは16Kがちょうど良いスイートスポットだと分かりました。しかし、それを収めるためにGPU側のスペースを少しだけ上げる必要があります(デフォルトでは約96GBなので):

$ sudo sysctl iogpu.wired_limit_mb=122880 

このモデルを動かすなら「llama.cpp」が最適だと思います(MLXはIQ2_XXSに量子化しないため):

$ llama-server \	 -m ~/.llama.cpp/models/Qwen3.5-397B-A17B-UD-IQ2_XXS/UD-IQ2_XXS/Qwen3.5-397B-A17B-UD-IQ2_XXS-00001-of-00004.gguf \	 --n-gpu-layers 99 \	 --ctx-size 16384 \	 --temp 1.0 --top-p 0.95 --top-k 20 

前回のredditで説明した私の現在のユースケースは、「子どもの学校の課題と進捗を理解するのに役立つ、最適なモデルの組み立て」を見つけることです。というのも、もし組織面が少しでもぐちゃぐちゃで、子どものデータがあるバラバラなシステムがいくつもあったり、コミュニケーションの不整合があったりするなら、それはまさに米国の公立学校の典型だからです。Claude Sonnetsの小さな軍隊がかなりうまくやってくれますが、とにかく高価です。だからこそ「Qwen3.5 397B」は、単なる置き換え(その希望)になり得るのではないかと思っています。

どのローカルモデルが「良い」仕事をするのかを理解するために、私はcupelを使いました: https://github.com/tolitius/cupel。そして次のステップは、起動して「Qwen3.5 397B」をマルチターン、ツール使用などのタスクでテストすることです:

https://preview.redd.it/hoy0uqr75yug1.png?width=2476&format=png&auto=webp&s=0caab1625168f52c74244175843644a600edcf28

そして、すべてのテストの結果として分かったのは、「Qwen3.5 397B IQ2」は……素晴らしいということです。2ビットであっても非常に賢く、ツールを呼び出せるだけでなく、ターン間でコンテキストを受け渡したり、めちゃくちゃな表の集合をきれいな集計に整理したり、などができます。

Qwen 3.5 122B 4bit」と同等ですが、その差を抽出するには、さらに精緻なプロンプト作りが必要だと思っています。

私を最も驚かせたのは、平均生成速度の1秒あたり29トークンです:

prompt eval time = 269.46 ms / 33 tokens ( 8.17 ms per token, 122.46 tokens per second) eval time = 79785.85 ms / 2458 tokens ( 32.46 ms per token, 30.81 tokens per second) total time = 80055.31 ms / 2491 tokens slot release: id 1 | task 7953 | stop processing: n_tokens = 2490, truncated = 0 srv update_slots: all slots are idle 

これは'llama.cpp"からの例の1つです。プロンプト処理はバッチ処理に依存しており、1秒あたり80トークンから330トークンの範囲でした

現時点で見えている欠点:

  • アセンブリで効率よく動かすことはできません。ロードできて収まる唯一のモデルだからです。122B(65GB)なら、まだ複数のモデルを並べて実行できます
  • ハードウェアのメモリ制限のため、大きなコンテキストをうまく扱えるとは期待していません
  • 理論上は、特定の専門家が必要な非常に専門的な知識に対処する場合の時間はより悪くなるはずですが、その重みは「潰れすぎて」いて、きれいな回答を出せません。ただ、おそらく「I」が「IQ2-XXS」に入っていることで、重要な重みが元の値に非常に近い状態に保たれているのかもしれません
  • 負荷がかかったとき、速度が1秒あたり30から17トークンに低下するのを見ました。プロンプトキャッシュがいっぱいになってエビクション(追い出し)が発生しているのが原因だと疑っていますが、さらに調査が必要です

しかし.. 512のエキスパート、保存済み知識397B、トークンあたり17Bのアクティブパラメータ、そしてノートPCで1秒あたり29トークン。

submitted by