# 帳票設計書 8-ベンチマークレポート

## 概要

本ドキュメントは、ベンチマーク実行結果をBenchmarkEntry形式で出力する帳票の設計を定義する。実行時間、スループット等の性能指標を含む。

### 本帳票の処理概要

ベンチマークレポートは、TensorFlowの操作やモデルの実行性能を測定し、BenchmarkEntries Protocol Buffers形式で結果を出力する帳票機能である。

**業務上の目的・背景**：TensorFlowの操作パフォーマンスの回帰テストやモデル推論速度の比較評価において、再現可能かつ機械的に処理可能なベンチマーク結果の記録が必要である。本帳票は標準化されたフォーマットで性能データを出力し、CI/CDパイプラインでの自動評価やバージョン間の性能比較を可能にする。

**帳票の利用シーン**：TensorFlowの新バージョンリリース前の性能回帰テスト、異なるハードウェア構成でのパフォーマンス比較、モデル最適化（量子化、プルーニング等）前後の性能比較、TF操作の単体ベンチマークなどで使用される。

**主要な出力内容**：
1. ベンチマーク名（クラス名.メソッド名形式）
2. イテレーション数（iters）
3. CPU時間（cpu_time）
4. ウォール時間（wall_time）
5. スループット（throughput、MB/s）
6. 追加情報（extras: メモリ使用量、トレース情報等）
7. メトリクス（metrics: name, value, min_value, max_value）

**帳票の出力タイミング**：`report_benchmark()`メソッドの呼び出し時、または`run_op_benchmark()`メソッドの完了時に自動的に出力される。

**帳票の利用者**：パフォーマンスエンジニア、TensorFlow開発者、QAエンジニア

## 帳票種別

性能評価レポート（BenchmarkEntries Protocol Buffers）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIベンチマーク実行 | N/A（`--benchmark_filter=`引数で実行） | Benchmarkクラスのbenchmarkメソッド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | Protocol Buffers（バイナリ）または標準出力（テキスト） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | `{TEST_REPORT_FILE_PREFIX}{mangled_name}`（環境変数で制御。"/"は"__"に変換） |
| 出力方法 | 環境変数`TEST_REPORT_FILE_PREFIX`設定時: ファイル出力、未設定時: 標準出力にテキスト表示 |
| 文字コード | N/A（バイナリ形式） / UTF-8（テキスト表示時） |

### PDF固有設定

N/A

### Excel固有設定

N/A

## 帳票レイアウト

### レイアウト概要

BenchmarkEntries Protocol Buffersメッセージとして出力される。各ベンチマーク実行ごとに1つのBenchmarkEntryが作成される。

```
[Protocol Buffers メッセージ構造]
+-------------------------------------+
| BenchmarkEntries                     |
|  +- entry[] (repeated BenchmarkEntry)|
|       +- name (string)              |
|       +- iters (int64)              |
|       +- cpu_time (double)          |
|       +- wall_time (double)         |
|       +- throughput (double)        |
|       +- extras (map<string,EntryValue>)|
|       +- metrics[] (BenchmarkEntry.MetricEntry)|
|            +- name (string)         |
|            +- value (double)        |
|            +- min_value (DoubleValue)|
|            +- max_value (DoubleValue)|
+-------------------------------------+
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | name | ベンチマーク名（ClassName.MethodName形式） | `_get_name()`メソッドで生成 | 文字列 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | iters | イテレーション回数 | `iters`引数 | 整数 | N/A |
| 2 | cpu_time | CPU実行時間（秒） | `cpu_time`引数 | 浮動小数点数 | N/A |
| 3 | wall_time | ウォール時間（秒） | `wall_time`引数 | 浮動小数点数 | N/A |
| 4 | throughput | スループット（MB/s） | `throughput`引数 | 浮動小数点数 | N/A |
| 5 | extras | 追加ベンチマーク情報 | `extras`引数（dict） | map<string, EntryValue> | N/A |
| 6 | metrics | メトリクスリスト | `metrics`引数（list of dict） | repeated MetricEntry | N/A |

### フッター部

N/A（Protocol Buffers形式のため）

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| Benchmarkクラスの継承 | BenchmarkまたはTensorFlowBenchmarkを継承 | Yes |
| benchmarkプレフィックス | メソッド名が"benchmark"で始まること | Yes |
| TEST_REPORT_FILE_PREFIX | ファイル出力時に必要な環境変数 | No（未設定時は標準出力） |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| N/A | N/A | N/A（実行順序で出力） |

### 改ページ条件

N/A

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A | N/A | N/A |

### テーブル別参照項目詳細

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| ベンチマーク名 | `type(calling_class).__name__ + "." + method_name` | N/A | スタックトレースからクラス名とメソッド名を取得（benchmark.py 行218-240） |
| wall_time（run_op_benchmark） | `_median(deltas)`（中央値） | N/A | benchmark.py 行375-381 |
| throughput（run_op_benchmark） | `mbs / median_delta` | N/A | benchmark.py 行401 |
| ファイル名 | `name.replace("/", "__")` | N/A | "/"を"__"に変換（benchmark.py 行132） |
| mean | `sum(x) / len(x)` | N/A | benchmark.py 行387 |
| stdev | `sqrt(sum((e-mean)^2 for e in x) / (len(x)-1))` | N/A | benchmark.py 行390-391 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[benchmarkメソッド呼び出し] --> B[run_op_benchmark or 手動実行]
    B --> C[burn_iters回のウォームアップ実行]
    C --> D[min_iters回の計測実行]
    D --> E[中央値・平均・標準偏差計算]
    E --> F[report_benchmark呼び出し]
    F --> G[_get_name: スタックトレースからベンチマーク名取得]
    G --> H[_global_report_benchmark呼び出し]
    H --> I[BenchmarkEntries proto構築]
    I --> J{TEST_REPORT_FILE_PREFIX設定?}
    J -->|Yes| K[ファイルにSerializeToString書き出し]
    J -->|No| L[標準出力にテキスト表示]
    K --> M[終了]
    L --> M
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| TypeError | extrasがdictでない | `extras must be a dict` | dict型を渡す |
| TypeError | metricsがlistでない | `metrics must be a list` | list型を渡す |
| TypeError | metricにnameフィールドがない | `metric must has a 'name' field` | nameキーを含むdictを渡す |
| TypeError | metricにvalueフィールドがない | `metric must has a 'value' field` | valueキーを含むdictを渡す |
| IOError | 出力ファイルが既に存在する | `File already exists: {path}` | 既存ファイルを削除するか別名にする |
| ValueError | 呼び出し元Benchmarkクラスが特定できない | `Unable to determine calling Benchmark class.` | Benchmarkクラス内から呼び出す |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1ベンチマーク実行あたり1エントリ |
| 目標出力時間 | ミリ秒以下（シリアライズ・書き込み） |
| 同時出力数上限 | N/A（各ベンチマークが独立したファイルに出力） |

## セキュリティ考慮事項

- ベンチマーク結果にはハードウェア性能情報が含まれるが、機密性は低い
- 出力先はファイルシステムの権限で保護される
- 環境変数TEST_REPORT_FILE_PREFIXの値はファイルパスとして使用されるため、パストラバーサルに注意

## 備考

- `_BenchmarkRegistrar`メタクラスにより、Benchmarkサブクラスは作成時に自動的に`GLOBAL_BENCHMARK_REGISTRY`に登録される（benchmark.py 行140-147）
- `ParameterizedBenchmark`メタクラスにより、パラメータ化されたベンチマークの自動生成が可能（benchmark.py 行150-200）
- `TensorFlowBenchmark`はBenchmarkの拡張で、`run_op_benchmark()`による自動計測機能を提供（benchmark.py 行288-408）
- `TF_OVERRIDE_GLOBAL_THREADPOOL`環境変数が設定され、各ベンチマークで新しいスレッドプールが割り当てられる（benchmark.py 行294）

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | test_log.proto | `tensorflow/core/util/test_log.proto` | BenchmarkEntries, BenchmarkEntry, MetricEntry, EntryValueの定義 |

**読解のコツ**: BenchmarkEntryのextrasフィールドはmap型で、値はEntryValue（double_valueまたはstring_value）。metricsはrepeated MetricEntryでname/value/min_value/max_valueを持つ。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | benchmark.py | `tensorflow/python/platform/benchmark.py` | `_global_report_benchmark()`関数（行59-137）がレポート出力の中心。BenchmarkEntries protoの構築とファイル出力を担当 |

**主要処理フロー**:
1. **行79-86**: ログ出力（ベンチマーク名、iters、wall_time、cpu_time、throughput）
2. **行88-122**: BenchmarkEntries proto構築（entry追加、extras/metricsのシリアライズ）
3. **行124-128**: 環境変数チェック（未設定時は標準出力にテキスト表示）
4. **行130-137**: ファイル出力（SerializeToStringでバイナリ書き出し）

#### Step 3: Benchmarkクラス階層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | benchmark.py | `tensorflow/python/platform/benchmark.py` | `Benchmark`クラス（行203-271）: `_get_name()`でスタックトレースからベンチマーク名を取得、`report_benchmark()`で`_global_report_benchmark`を呼び出す |
| 3-2 | benchmark.py | `tensorflow/python/platform/benchmark.py` | `TensorFlowBenchmark`クラス（行288-420）: `run_op_benchmark()`でburn_iters/min_itersの自動計測とメディアン計算を実施 |

#### Step 4: ベンチマーク実行フレームワークを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | benchmark.py | `tensorflow/python/platform/benchmark.py` | `_run_benchmarks()`（行423-464）、`benchmarks_main()`（行467-489）: `--benchmark_filter=`引数によるベンチマーク選択と実行 |

### プログラム呼び出し階層図

```
benchmarks_main() [行467]
    |
    +-- _run_benchmarks(regex) [行423]
            |
            +-- GLOBAL_BENCHMARK_REGISTRY から一致するベンチマークを検索
            +-- benchmark_instance.benchmark_xxx() [ユーザー定義メソッド]
                    |
                    +-- run_op_benchmark() [行303] (TensorFlowBenchmark)
                    |       |
                    |       +-- sess.run() x burn_iters (ウォームアップ)
                    |       +-- sess.run() x min_iters (計測)
                    |       +-- _median() / _mean_and_stdev() (統計計算)
                    |       +-- report_benchmark() [行242]
                    |
                    +-- report_benchmark() [行242] (手動呼び出し)
                            |
                            +-- _get_name() [行218] (スタックトレースから名前取得)
                            +-- _global_report_benchmark() [行59]
                                    |
                                    +-- BenchmarkEntries proto構築
                                    +-- ファイル出力 or 標準出力
```

### データフロー図

```
[入力]                         [処理]                         [出力]

Session + Op --------+
                     |
burn_iters (int) ---+---> run_op_benchmark()
                     |      |
min_iters (int) ----+      +-- 時間計測 (time.time())
                     |      +-- median/mean/stdev計算
mbs (float) --------+      +-- report_benchmark()
                     |              |
extras (dict) ------+              +-- _global_report_benchmark()
                     |                      |
metrics (list) -----+                      +-- BenchmarkEntries proto
                                            |
                                            v
                        TEST_REPORT_FILE_PREFIX設定? -> ファイル or 標準出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| benchmark.py | `tensorflow/python/platform/benchmark.py` | ソース | ベンチマークフレームワーク全体（行1-490） |
| test_log.proto | `tensorflow/core/util/test_log.proto` | 定義 | BenchmarkEntries Protocol Buffers定義 |
| test_log_pb2.py | `tensorflow/core/util/test_log_pb2.py` | 生成コード | protoから自動生成されたPythonバインディング |
| timeline.py | `tensorflow/python/client/timeline.py` | ライブラリ | Chrome Trace Format生成（store_trace時） |
| gfile.py | `tensorflow/python/platform/gfile.py` | ライブラリ | ファイルI/O操作 |
| tf_inspect.py | `tensorflow/python/util/tf_inspect.py` | ユーティリティ | スタックトレース取得 |
