ベンチマークメトリクス仕様
バージョン: 0.4.0 ステータス: 実装済み スコープ:
asiai bench— 全エンジン
背景
ベンチマーク結果はエンジン間で比較可能でなければなりません。各メトリクスには、すべてのエンジン実装が尊重すべき単一の定義があります。実装は異なる場合があります(サーバーサイドAPIまたはクライアントサイド測定)が、セマンティクスは同一でなければなりません。
メトリクス
M1. tok_per_sec — 生成速度
定義: プロンプト処理(TTFT)を除く生成時間のみの1秒あたり生成トークン数。
generation_s = total_duration_s - ttft_s
tok_per_sec = tokens_generated / generation_s (if generation_s >= 0.01)
= 0.0 (otherwise)
| エンジン | generation_s のソース |
|---|---|
| Ollama | eval_duration / 1e9(サーバーAPI — 直接) |
| OpenAI互換 | elapsed_s - (ttft_ms / 1000)(クライアントサイド) |
根拠: 大規模コンテキストサイズ(例:64kトークン)では、TTFTが総時間を支配する場合があります。tok/sにTTFTを含めると、高速ジェネレーターが遅く見えます(例:42 tok/sではなく3.2 tok/s)。
M2. ttft_ms — 最初のトークンまでの時間
定義: リクエスト送信から最初の出力トークン受信までの時間(ミリ秒)。
| エンジン | ソース |
|---|---|
| Ollama | prompt_eval_duration / 1e6(サーバーAPI) |
| OpenAI互換 | (time.monotonic() at 1st content chunk - t0) * 1000(クライアント) |
注意:セマンティクスはわずかに異なります(サーバーとクライアントの測定)が、ローカルホストでの差は約1ms — 許容範囲です。
M3. total_duration_ms — 総時間
定義: リクエストのウォールクロック総時間(プロンプト処理 + 生成)、ミリ秒。
不変条件: total_duration_ms >= ttft_ms — 常に。
| エンジン | ソース |
|---|---|
| Ollama | total_duration / 1e6(サーバーAPI) |
| OpenAI互換 | elapsed_s * 1000(クライアントウォールクロック) |
M4. tokens_generated — トークン数
定義: モデルが生成した出力トークンの数。
ソース(優先順位):
1. サーバーカウンター: Ollama eval_count、OpenAI互換 usage.completion_tokens
2. テキスト長推定: max(1, len(text) // 4)(ヒューリスティック:約4文字/トークン)
3. 絶対に len(text_parts) を使用しない(SSEチャンク ≠ トークン)
M5. generation_duration_ms — 生成時間
定義: 生成時間のみ(TTFTを除く)、ミリ秒。
分解 total = ttft + generation を明示的かつ監査可能にします。
| エンジン | ソース |
|---|---|
| Ollama | eval_duration / 1e6(サーバーAPI — 直接) |
| OpenAI互換 | max(0, elapsed_s - ttft_s) * 1000(計算値) |
M6. power_watts — GPU電力
定義: この特定のエンジンの実行中の平均GPU電力(ワット)。
スコープ: エンジンごとに1つの PowerMonitor。最初のプロンプトの前に開始し、最後の実行の後に停止。各エンジンが独自の測定を取得 — セッション全体の平均ではありません。
ソース: sudo powermetrics(macOS)。
M7. tok_per_sec_per_watt — エネルギー効率
tok_per_sec_per_watt = tok_per_sec / power_watts
補正済みtok/s(M1)とエンジンごとの電力(M6)を使用。
M8. std_dev_tok_s — 分散(プールド)
定義: プールドプロンプト内標準偏差 — プロンプト間の分散を混在させずに、実行間のノイズを捕捉します。
For each prompt_type p with runs [v1, v2, ..., vn]:
var_p = sum((vi - mean_p)^2) / n (population variance)
pooled_variance = mean(var_p for all p with n >= 2)
std_dev_tok_s = sqrt(pooled_variance)
安定性分類(変更なし):
- CV < 5% → stable
- CV < 10% → variable
- CV >= 10% → unstable
CV = (std_dev_tok_s / avg_tok_s) * 100
実装マップ
| メトリクス | base.py |
ollama.py |
openai_compat.py |
runner.py |
reporter.py |
|---|---|---|---|---|---|
| M1 tok/s | フィールド | サーバーAPI | クライアント(TTFT除外) | パススルー | 平均 |
| M2 ttft_ms | フィールド | サーバーAPI | クライアントストリーミング | パススルー | 平均 |
| M3 total_duration_ms | フィールド | サーバーAPI | クライアントウォールクロック | パススルー | 平均 |
| M4 tokens_generated | フィールド | サーバーAPI | サーバーまたは len//4 |
パススルー | 平均 |
| M5 generation_duration_ms | フィールド | サーバーAPI | 計算値 | dictに保存 | — |
| M6 power_watts | — | — | — | エンジンごとのモニター | パススルー |
| M7 tok/s/W | — | — | — | 計算値 | パススルー |
| M8 std_dev | — | — | — | — | プールドプロンプト内 |
ベンチマークプロトコル
- ウォームアップ: エンジンごとに1回の計測外生成(
"Hello"、max_tokens=1)でキャッシュをプライミング。 - 計測実行: デフォルトでプロンプトごと・エンジンごとに3回実行(
--runsで設定可能)。 - サンプリング: 決定論的出力のため、全エンジンで
temperature=0(グリーディ)。 - レポーティング: 中央値tok/sをプライマリメトリクス(SPEC標準)、平均 +/- 標準偏差をセカンダリとして使用。
- スロットリング: いずれかの実行中に
thermal_speed_limit < 100%の場合に警告を出力。 - メタデータ: engine_version、model_format、model_quantization、hw_chip、os_version を再現性のために結果ごとに保存。
完全な手法監査については benchmark-best-practices.md を参照してください。