# 通知設計書 15-StopAtStepHook

## 概要

本ドキュメントは、TensorFlowの`StopAtStepHook`（SessionRunHook）の通知設計について記載する。このフックは、指定されたステップ数に到達した際にトレーニングの停止を要求する通知機構である。

### 本通知の処理概要

`StopAtStepHook`は、トレーニングが指定ステップ数（`num_steps`）を実行するか、指定のグローバルステップ（`last_step`）に到達した時点で`run_context.request_stop()`を呼び出し、`MonitoredSession`のトレーニングループを停止させる。

**業務上の目的・背景**：トレーニングの実行ステップ数を事前に制御することで、計算リソースの効率的な利用、実験の再現性確保、およびトレーニング時間の管理を実現する。分散トレーニング環境でも各ワーカーの停止タイミングを統一的に制御できる。

**通知の送信タイミング**：各`session.run()`の実行後（`after_run`フック）にグローバルステップを確認し、`last_step`に到達した場合に停止要求を発行する。

**通知の受信者**：`MonitoredSession`（トレーニングループ制御機構）。`request_stop()`により`MonitoredSession`の内部フラグが設定され、次のイテレーション判定で停止が決定される。

**通知内容の概要**：停止要求シグナル（`request_stop()`呼び出し）。明示的なメッセージ出力は行わない。

**期待されるアクション**：`MonitoredSession`がトレーニングループの停止を実行し、後続のクリーンアップ処理（チェックポイント保存、フック`end()`呼び出し等）が行われる。

## 通知種別

プログラム内部通知（`run_context.request_stop()` によるMonitoredSessionへの停止要求シグナル）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（after_runフック内で即時実行） |
| 優先度 | 高（トレーニング停止に直結する制御シグナル） |
| リトライ | 無し（停止要求は冪等操作） |

### 送信先決定ロジック

- `run_context.request_stop()`を呼び出し、`MonitoredSession`に停止を通知
- 停止判定はグローバルステップテンソルの値に基づく

## 通知テンプレート

### 停止要求の場合

本フックは明示的なメッセージを出力しない。`request_stop()`による内部シグナルのみ。

### 本文テンプレート

該当なし（メッセージ出力なし）

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| global_step | 現在のグローバルステップ値 | `session.run(_global_step_tensor)` | Yes |
| last_step | 停止対象ステップ | `num_steps + 初期global_step` or コンストラクタ引数 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| SessionRunHook | `after_run` | `global_step >= last_step` | グローバルステップが最終ステップ以上の場合、再度session.runで最新値を確認してからrequest_stop() |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| global_step < last_step | グローバルステップが最終ステップ未満の場合、停止要求を行わない |
| stale値による二重チェック | before_runで取得した値が条件を満たしても、after_runで最新値を再取得して確認（行450-453） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[begin発火] --> B[_global_step_tensor取得]
    B --> C[after_create_session発火]
    C --> D{last_step未設定?}
    D -->|Yes| E[last_step = global_step + num_steps]
    D -->|No| F[last_step使用]
    E --> G[トレーニングループ開始]
    F --> G
    G --> H[before_run: global_step_tensor要求]
    H --> I[session.run実行]
    I --> J[after_run発火]
    J --> K{run_values.results + 1 >= last_step?}
    K -->|No| G
    K -->|Yes| L[session.runで最新global_step取得]
    L --> M{step >= last_step?}
    M -->|No| G
    M -->|Yes| N[run_context.request_stop]
    N --> O[トレーニング停止]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（データベースを使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ValueError | `num_steps`と`last_step`のどちらも未指定、または両方指定 | コンストラクタで例外送出（行423-426） |
| RuntimeError | グローバルステップテンソルが未作成 | `begin()`で例外送出（行432-433） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | 1回（停止要求は最大1回のみ発行される） |

### 配信時間帯

制限なし

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

- グローバルステップ値のみを参照する安全な操作
- 外部へのデータ送信は行わない

## 備考

- `before_run`で`_global_step_tensor`を`SessionRunArgs`として要求し（行441）、`after_run`で`run_values.results + 1`として次ステップの値を推定する
- stale値問題に対処するため、条件を満たした場合に再度`session.run`で最新値を確認する二重チェック機構がある（行450-453）
- `_MultiStepStopAtStepHook`（行328-389）はEstimator向けの拡張版で、`steps_per_run`変数によるtf.while_loop対応を行う

---

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

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

### 推奨読解順序

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

SessionRunHookのライフサイクルとrequest_stopの仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | session_run_hook.py | `tensorflow/python/training/session_run_hook.py` | SessionRunHook（行94-182）とSessionRunContext.request_stop（行253-259） |

**読解のコツ**: `request_stop()`は`MonitoredSession`の内部フラグを設定するだけであり、即座にトレーニングが停止するわけではない。次のwhile判定で停止が反映される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | basic_session_run_hooks.py | `tensorflow/python/training/basic_session_run_hooks.py` | StopAtStepHook.__init__（行404-428）で`num_steps`/`last_step`の排他バリデーション |

**主要処理フロー**:
1. **行423-426**: num_stepsとlast_stepの排他チェック
2. **行427-428**: インスタンス変数への設定

#### Step 3: ステップ管理ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | basic_session_run_hooks.py | `tensorflow/python/training/basic_session_run_hooks.py` | begin/after_create_session/before_run/after_run（行430-453）の一連のフロー |

**主要処理フロー**:
- **行430-433**: `begin` - グローバルステップテンソルの取得
- **行435-438**: `after_create_session` - num_steps指定時のlast_step計算
- **行440-441**: `before_run` - global_step_tensorのfetch要求
- **行443-453**: `after_run` - stale値での事前判定と、最新値での二重チェック

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

```
MonitoredTrainingSession
    │
    ├─ StopAtStepHook.begin() [行430-433]
    │      └─ training_util._get_or_create_global_step_read()
    │
    ├─ StopAtStepHook.after_create_session() [行435-438]
    │      └─ session.run(_global_step_tensor) ※num_steps時のlast_step計算
    │
    ├─ [各ステップのループ]
    │      ├─ StopAtStepHook.before_run() [行440-441]
    │      │      └─ SessionRunArgs(_global_step_tensor)
    │      │
    │      └─ StopAtStepHook.after_run() [行443-453]
    │             ├─ run_values.results + 1 >= last_step? [行444-445]
    │             ├─ session.run(_global_step_tensor) [行451] ※二重チェック
    │             └─ run_context.request_stop() [行453]
    │
    └─ MonitoredSession: should_stop() → True
```

### データフロー図

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

num_steps / last_step    ───▶ __init__()                 ───▶ last_step設定
                               │
global_step_tensor       ───▶ before_run() → after_run()  ───▶ request_stop()
                               │                                 │
                               └─ ステップ比較判定                └─ MonitoredSession停止
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| basic_session_run_hooks.py | `tensorflow/python/training/basic_session_run_hooks.py` | ソース | StopAtStepHookクラス定義（行393-453） |
| basic_session_run_hooks.py | `tensorflow/python/training/basic_session_run_hooks.py` | ソース | _MultiStepStopAtStepHook拡張版（行328-389） |
| session_run_hook.py | `tensorflow/python/training/session_run_hook.py` | ソース | SessionRunHook基底クラス、SessionRunContext.request_stop |
| training_util.py | `tensorflow/python/training/training_util.py` | ソース | `_get_or_create_global_step_read`関数 |
