AI・機械学習
同じモデル、同じQ4_K_Mラベル:5.02、5.07、5.27ビット/重み
Same model, same Q4_K_M label: 5.02, 5.07 and 5.27 bits per weight (github.com)
要約
picchioは、ローカルLLMのパフォーマンスを測定するためのPythonツールです。モデルの量子化ラベルが同じでも、実際のビット/重みやトークン/秒(tok/s)の速度が異なる場合があることを示し、GPUオフロードの失敗やCPUフォールバックといった問題点を明らかにします。このツールは、プリフィル、デコード、ウォールクロックの各速度を分離して計測し、GPUが実際に処理を行っているか、その理由を検証します。
全文翻訳
picchio ローカルLLMを測定する単一のPythonファイル:実効ビット/重み、3つのtok/sレーン、およびサイレントCPUフォールバック。
インストール · コマンド · 量子化 · レーン · 測定 · 例
ほとんどのGPU速度の主張は、1つのtok/sの数値です。その数値は正しくても、間違ったストーリーを伝える可能性があります。
3つの失敗モード、それぞれ1つのコマンド:
同じQwen3.5-9Bの4つの量子化、すべてQ4_K_Mとラベル付けされているが、実測値は5.02、5.02、5.07、5.27ビット/重み(量子化ラベル)です。
同じモデルとファイルで、GPUコストがプリフィルで22倍、デコードで2倍未満になる(3つのレーン)。
ベアのllama.cppから記憶していた36 tok/sが、32セル行列のどのセルでも再現されませんでした(サイレントCPUフォールバック)。
picchioは、プリフィル、デコード、ウォールクロックを分割し、エンジンのログをOSのGPUメーターと照合して読み取り、GPUが処理を行ったかどうか、そしてその理由を示す判定を出力します。
インストール
curl -fsSLO https://raw.githubusercontent.com/logxio/picchio/main/picchio.py
python3 picchio.py
引数なしで実行すると、モデル(ollamaタグ、カレントフォルダ、HFおよびLM Studioキャッシュ)を検索し、選択したモデルを実行します。
.ggufパスは完全なllama.cpp診断を取得し、ollamaタグは測定モードを取得します。
python3とllama.cppまたはollamaが必要です。
固定プロンプトで3回実行、最初の実行はコールドスタートです。
GPUが稼働している場合は約1分、CPUの場合は数分かかります。
~/.cache/picchioの下に1つのキャッシュファイルを作成し、それ以外は何も作成しません。
python3 picchio.py --selftest は、examples/raw/ の生のエンジンログをリプレイし、コミットされたすべての判定ブロックを1行ずつ再現する必要があります。バッジはプッシュごとにこれを実行します。
コマンド
表では、picchio は python3 picchio.py を表します。
コマンド | 何をするか | 実際の出力
---|---|---
picchio model.gguf | 完全なllama.cpp診断:3回のパス、配置、コールドスタートの内訳、判定 | 例
picchio qwen3.5:9b | ローカルのollamaサーバーを介した同じパス、メモリ分割からの配置 | 例
picchio http://127.0.0.1:8080 | 実行中のllamaサーバーを測定、何も起動せず、ウォームアップのみ | 例
picchio guard -- <command> | 独自のコマンドをラップし、レイヤーがGPUにロードされた瞬間に警告、決して終了させない | 例
picchio compare A.txt B.txt | 保存された2つのブロックを1つずつ比較、最初の設定差が原因となる | 例
picchio verify FILE | 数字が矛盾する貼り付けられたブロックにフラグを立てる | 例
picchio watch [PID] | OSのGPUメーターをプロセスまたはGPU全体に向ける(macOS) | 例
picchio plan [MODEL] | 収まるか、ggufヘッダーから価格設定。デコード推定値は測定後に表示 | 例
picchio id MODEL | 量子化ラベルを分割:テンソルタイプミックスごと、実効ビット/重み、KV dtype、エキスパート | 例
picchio --explain 36 | ここで測定されたレーンに対して見た数値を分類(キャッシュレート、再実行なし) | 例
picchio model.gguf --ctx-sweep | 複数のコンテキスト深度でレーンを再測定し、減衰スロープを報告 | 例
watch は実際の作業と並行して実行され、何も起動せず、何もアンロードしません。
--for はサンプリングウィンドウ(秒単位)、--engine ollama は評価対象のモデル名を指定します。
python3 picchio.py watch --engine ollama --for 8 --passes N | 測定パス、最初のパスはコールド(デフォルト3)
--keep-logs DIR | 各パスの生のエンジン出力をDIRに保存、macOSおよびNVIDIA LinuxではサンプリングされたGPUカーブ(telemetry.json)も保存
--no-telemetry | OS側のGPUサンプリングをスキップ。os行は、判定がエンジン+タイミングのみに基づくと表示します。
--json | ブロック後の機械可読測定値
--bin PATH | llama.cppバイナリを自分で選択
--selftest | examples/raw をリプレイし、コミットされた判定を検証
--version | バージョンと測定プロトコルを表示
ベアの -- の後のすべては、llama.cppバイナリに直接渡されます。
ターミナルでのみ色が表示されます(NO_COLORを尊重)。パイプ出力はプレーンASCIIです。
スクリプト用の終了コード:0 正常または証拠なし、2 実行不可、3 部分的なオフロード、4 サイレントCPUフォールバック、5 矛盾する証拠。
guard はラップされたコマンド自身の終了コードを渡します(シグナルで終了した場合は128 + シグナル番号)。compare は両方のブロックが解析されると0で終了します。verify はブロックが自己整合している場合は0で、ソースが競合している場合は5で終了します。watch はGPUが動作している場合は0で、アイドル状態の場合は4で終了します。
量子化ラベル
picchio id MODEL は、ggufテンソルテーブルをウォークし、各テンソルをggmlタイプごとに価格設定します。当社のQ4_K_Mは、名前に含まれる4を27%上回る5.07ビット/重みを測定します。4.50から32.00ビットまでの5つのテンソルタイプの混合であり、ヘッダー自身のバイトオフセットは、カードが印刷する前に同じ合計に監査する必要があります。
同じQwen3.5-9Bが同じQ4_K_Mラベルの下で、4つの量子化器にわたって5.02、5.02、5.07、5.27ビット/重みを測定します。これは、4つのファイルすべてが共有する427個のテンソル(examples/quantizers/)上でのことです。
ラベルは同じテンソルセットを約束することさえしません。1つの量子化器は、q8_0としてメインファイル内に243MパラメータのMTPヘッドを出荷し、別のものは同じヘッドを別個のリポジトリとして出荷します。
KVキャッシュのdtypeはファイルに含まれていません。カードは、ここで測定された最後の実行を参照します。
エキスパートの混合では、トークンごとに何人のエキスパートがウェイクするかを報告します(examples/id-35b.txtは256人中8人、トークンあたり約3.5Bの重み、合計34.7B)。
.ggufパスまたはollamaタグで動作します。読み取り専用、終了コード0。
3つのレーン
プリフィル(他ではプロンプト処理またはppと呼ばれる)は、モデルがプロンプトを読み取る速度です。デコード(tgまたはeval)は、回答を書き込む速度です。ウォールクロックは、生成されたトークンを、ロードとウォームアップを含むすべてで割ったものです。
レーンは個別に失敗します。チャートは例/の2つの実際の実行、CPU側のCPUスレッドの4/10です。
プリフィルは、長いプロンプトでの最初のトークンまでの時間を設定します。500 tok/sを示すMacのスクリーンショットは、ほぼ常にプリフィルです。
サイレントCPUフォールバック
同じマシン、同じモデル、同じファイル、CPUに強制(examples/cpu-fallback.txt):
WHY行は、実行自体の証拠で証明できる最初の原因の名前を付けます。または不明と表示します。
アプリを構築するためにローカルモデルを測定していた数週間、ベアのllama.cppは36 tok/sを、アプリを介した同じモデルは11.5 tok/sを生成しました。そのギャップが、このリポジトリが存在する理由です。
CPUとGPU、コールドとウォームにわたる32セル行列は、どのセルでも36を再現しませんでした。これは、別のレーンから記憶された生成速度のレートです。
行列が明らかにしたのは、このサイレントフォールバックでした。
OS行
パスの実行中、バックグラウンドスレッドがOS自身のGPUメーターを読み取ります。macOSでは、4Hzのioregとpowermetricsエネルギーカウンターからsudoを引いたもの。NVIDIA Linuxでは、ドライバーのNVMLです。
それがOS行です。
GPUが平坦なままだったOSが見たGPUでの完全なオフロードの主張は、矛盾する証拠(終了コード5)です。
GPU証拠がなく、メーターがGPUのアイドル状態を監視しているビルドは、サイレントCPUフォールバック(終了コード4)であり、実際の誤って構築されたバイナリで測定されます。
ソースの欠落は棄権します。行は、どの証拠が残っているかを示します。
llama-bench
lama-benchは異なる質問に答えます。
このマシンとモデルの定常状態のppとtg、ここで測定、同じモデル、同じ日:
ツール | 設定 | プロンプト側 | 生成側 | メモ
---|---|---|---|---
lama-bench, default | pp256: 597.06 | tg64: 20.21 | バックエンド列:BLAS,MTL
lama-bench, -ngl 0 (CPU) | pp256: 27.82 | tg64: 11.90 | バックエンド列:BLAS,MTL
レンタルした4090も同じです。そのCUDAビルドは、CUDAをその列で-ngl 0に保ちます。
21倍のプロンプトサイドの崩壊は、CPU実行の唯一の可視的な痕跡です。ロード時間、コールド/ウォームスプリット、判定はありません。
測定されたApple M5、32 GB、macOS 26.5.1、llama.cppビルド9430およびollama 0.31.1。
約730のプロンプトトークンと128の生成トークン/パス、3回のパス、最初のパスはコールドです。
そのプロトコルは各ブロックフッター(mp1)で名前が付けられています。それが変更されると、タグも変更されます。
レーン列はウォームメディアンを保持します。最初の3行と4090行の背後にある生のエンジン出力は、examples/raw/ にあり、--keep-logs によって書き込まれます。
マシン | モデル | エンジン | プロトコル | プリフィル | デコード | ウォールクロック | 判定
---|---|---|---|---|---|---|---
Apple M5, 32 GB | Qwen3.5-9B Q4_K_M, llama.cpp b9430 | mp1 | 588.0 | 21.1 | 15.5 | HEALTHY
Apple M5, 32 GB | same, forced CPU (0/33 layers) | mp1 | 26.8 | 12.2 | 3.0 | SILENT CPU FALLBACK
Apple M5, 32 GB | qwen3.5:9b, ollama 0.31.1 | mp1 | 833.8 | 21.3 | 18.1 | HEALTHY
Apple M5, 32 GB | Qwen3.6-35B-A3B UD-Q4, llama.cpp | mp1 | 787.3 | 34.4 | 19. | HEALTHY