diff --git a/CLAUDE.md b/CLAUDE.md index 3288a94..9b52071 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,6 +20,8 @@ 補足: **Step 8-12 完了**.Helmholtz 相反原理を Mitsuba 上で実証検証.`schema.py` の RenderConfig に `ptracer` integrator を追加,`configs/scene_baseline_perspective_{path,ptracer}.yaml` で perspective sensor + scalar_rgb + spp=4096 で比較.**bot/top 比が path 2.035 vs ptracer 2.006 で誤差 1.4% で一致**=形は方向独立.絶対値は Mitsuba 実装の正規化差で 1.99× 違うが形(空間パターン)は同じ.副次的発見: **orthographic + ptracer は Mitsuba 3 では実行不能**(`Endpoint::sample_direction()` 未実装).これにより「方向変更で形を実機に近づける道は無い」が確定し,**LSC モデル化が唯一の道**である結論が強化された. 次のアクション(キャリブ再開時): 残差に **LSC(ISP レンズシェーディング)順方向モデル**を当てる(物理動機づけ低自由度形、overfitting 回避・取得パラメータ数明記). +補足: **速度最適化ワーク開始**(キャリブ作業を一旦中断).[TEST_04 シミュレーション速度最適化履歴](docs/06_TEST/TEST_04_シミュレーション速度最適化履歴.md) に試行を集約.**Speed-0 ベースライン計測完了**(`configs/scene_baseline.yaml`,3 回中央値): **B1 sm-render = 507.86 s(≈8.46 分)/ B2 sm-visualize path bake (samples=16) = 55.97 s**.**副次発見**: `DRJIT_LIBLLVM_PATH` 環境変数の消失で sm-render が ImportError でクラッシュしていたことを発見.`C:\Program Files\LLVM\bin\LLVM-C.dll` を発見し **User scope に永続化**して復旧.sm-visualize の direct bake は内部 scalar_rgb 固定のため過去ログでも警告は出ていたが完走していた.**方向修正**: Speed-1 当初の「JIT 有効化で高速化」は既に JIT 経路に乗っているため不成立 → 「LLVM-C.dll 自動検出と診断ログ」に再定義(再発防止).**本命の高速化レバーは Speed-2 path bake wavefront 化**(10× 以上見込み).GPU は Intel HD Graphics 520 のみで CUDA 不可,CPU 側完結方針.精度(spp/max_depth)は不変. + 実装済みモジュール: - `src/sm_tias_lightsim/uniformity.py` — Rec.709 輝度変換 + CoV/std/max-min(MiniTias-Evaluation コピー) - `src/sm_tias_lightsim/evaluation/zones.py` — 正規化楕円距離マップ + 3 ゾーン分類 + ゾーン別統計 diff --git "a/docs/06_TEST/TEST_04_\343\202\267\343\203\237\343\203\245\343\203\254\343\203\274\343\202\267\343\203\247\343\203\263\351\200\237\345\272\246\346\234\200\351\201\251\345\214\226\345\261\245\346\255\264.md" "b/docs/06_TEST/TEST_04_\343\202\267\343\203\237\343\203\245\343\203\254\343\203\274\343\202\267\343\203\247\343\203\263\351\200\237\345\272\246\346\234\200\351\201\251\345\214\226\345\261\245\346\255\264.md" new file mode 100644 index 0000000..e07283e --- /dev/null +++ "b/docs/06_TEST/TEST_04_\343\202\267\343\203\237\343\203\245\343\203\254\343\203\274\343\202\267\343\203\247\343\203\263\351\200\237\345\272\246\346\234\200\351\201\251\345\214\226\345\261\245\346\255\264.md" @@ -0,0 +1,280 @@ +# シミュレーション速度最適化履歴 (Performance Optimization History) + +本ドキュメントは SmTIAS-LightSim のシミュレーション・可視化処理の **実行時間最適化** の試行を時系列で記録する. + +目的: + +- 「どの仮説でどの最適化を入れ,実時間がどう変わったか」を **数値で残す**. +- **効かなかった試行も同等に記録**し,同じ最適化を繰り返し試す事態を防ぐ. +- 各試行の **学び** を明示し,次に取り組むべきボトルネックを判断する根拠を蓄積する. + +関連ドキュメント: + +- 関連: [TEST_01 キャリブレーション検証履歴](TEST_01_キャリブレーション検証履歴.md)(精度側の試行) +- 関連: [TEST_02 シミュレーション実行記録](TEST_02_シミュレーション実行記録.md)(output/ 索引) + +## 大前提 (Constraints) + +| 項目 | 値 | +| --- | --- | +| ターゲット環境 | Windows 11 Pro 10.0.22631 / PowerShell 5.1 | +| GPU | Intel HD Graphics 520(NVIDIA 非搭載) | +| Mitsuba CUDA variant | **使用不可**(CUDA 対応 GPU が無いため) | +| 精度方針 | **現精度(spp/max_depth)を維持したまま実行時間のみ短縮**.サンプル数削減やサンプラ変更による「分散↓→ spp 削減」系の最適化は対象外. | +| 数値同等性 | 各最適化試行は `luminance.npy`(および bake 出力)の数値同等性を確認した上で適用する. | + +## ベンチマーク条件 (Benchmark Conditions) + +すべての試行は以下の固定条件で測定する(条件を変えた場合は当該試行内に明記). + +### 標準ベンチマーク + +| 項目 | 値 | +| --- | --- | +| **標準シーン** | `configs/scene_baseline.yaml`(メイン構成.`llvm_ad_rgb` / spp=1024 / max_depth=8) | +| **B1: sm-render コマンド** | `uv run sm-render configs/scene_baseline.yaml --output output/_bench/luminance.npy` | +| **B2: sm-visualize (path bake) コマンド** | `uv run sm-visualize configs/scene_baseline.yaml --bake-mode path --bake-samples 16 --bake-cache output/_bench/bake.npz --screenshot output/_bench/bake.png --no-show` | +| **計測方法** | `Measure-Command { … }` の `TotalSeconds`.**warm-up 1 回を捨て,3 回測って中央値**を採用. | +| **環境** | 計測中は他の重い処理を閉じる.電源プロファイル `High performance` 推奨. | +| **出力先** | `output/_bench/`(gitignore 配下,数値のみドキュメントに転記) | + +### 計測コマンド(PowerShell スニペット) + +```powershell +# B1: sm-render +1..4 | ForEach-Object { + $t = Measure-Command { + uv run sm-render configs/scene_baseline.yaml ` + --output output/_bench/luminance.npy + } + "$_ $($t.TotalSeconds) s" +} + +# B2: path bake +1..4 | ForEach-Object { + Remove-Item output/_bench/bake.npz -ErrorAction SilentlyContinue + $t = Measure-Command { + uv run sm-visualize configs/scene_baseline.yaml ` + --bake-mode path --bake-samples 16 ` + --bake-cache output/_bench/bake.npz ` + --screenshot output/_bench/bake.png --no-show + } + "$_ $($t.TotalSeconds) s" +} +``` + +> 1 回目は warm-up(変動が大きい)として捨て,2〜4 回目の中央値を採用する. + +### 数値同等性検証 (Equivalence Check) + +各試行で出力に対し以下を確認する: + +| 出力 | 同等性基準 | +| --- | --- | +| `luminance.npy` | **平均相対誤差 < 1e-6**(決定論的最適化=同じビット列出力が理想),MC サンプラの初期化規約が変わる場合は **5σ 以内の統計同等性**(同 spp で再計測して比較) | +| `bake.npz`(face_values) | 同上 | + +## 俯瞰サマリ (Overall Progression) + +時系列の主要計測値.**速度比** = ベースライン時間 / 当該試行時間(大きいほど速い). + +| ID | 試行 | B1: sm-render | B1 速度比 | B2: path bake | B2 速度比 | 数値同等性 | +| --- | --- | --- | --- | --- | --- | --- | +| Speed-0 | ベースライン(LLVM JIT 復元後) | **507.86 s** | 1.0× | **55.97 s** | 1.0× | — | + +(試行を追加するごとに行を append) + +## イテレーション履歴 (Iteration Log) + +### イテレーションのテンプレート + +各試行は以下の見出しで記述する: + +- **日付**: YYYY-MM-DD +- **コミット**: ``(試行が完了した時点のコミット) +- **背景・問題意識**: なぜこの最適化を考えたか +- **仮説(技術的根拠)**: なぜ速くなると考えるか(JIT 経路・並列化機構等の物理的・実装的根拠) +- **試した変更**: コード/設定の差分(ファイル名・行レベルで具体的に) +- **期待した効果**: 何倍速くなることを期待したか +- **計測コマンド**: 実行したコマンド全文 +- **計測結果**: 3 回計測の中央値(warm-up 除く.生データも参考に記載) +- **数値同等性**: luminance.npy / bake.npz の比較結果 +- **解釈**: なぜ効いた/効かなかったか +- **学び**: 次の試行への含意 +- **次のアクション**: 次にやること + +--- + +### Speed-0: ベースライン計測 (Baseline) + +- **日付**: 2026-05-28 +- **コミット**: `4e93638`(feature/baseline-calibration の最新.feature/perf-optimization から派生) +- **背景・問題意識**: 改善前の実時間を確定する.これ以降の試行はすべてこの値との比較で評価する. +- **仮説(技術的根拠)**: なし(計測のみ). + +#### 計測前に判明した重大事項(環境破綻と復旧) + +**現象**: 計測を開始しようとしたところ,sm-render が以下のエラーで即時クラッシュした. + +``` +jitc_llvm_init(): LLVM API initialization failed .. +ImportError: jit_init_thread_state(): the LLVM backend is inactive because the LLVM shared library +("LLVM-C.dll") could not be found! Set the DRJIT_LIBLLVM_PATH environment variable to specify its path. +``` + +`feature/baseline-calibration`(前ブランチ)でも同じエラー → **コード変更に依存しない環境問題**であることが確定. + +**調査結果**: + +| 項目 | 状態 | +| --- | --- | +| `LLVM-C.dll` の実在 | **あり**: `C:\Program Files\LLVM\bin\LLVM-C.dll`(過去にインストール済み) | +| `DRJIT_LIBLLVM_PATH` 環境変数 | **未設定**(User / Machine 両方とも) | +| PATH 内の LLVM bin | **未登録** | +| sm-visualize の direct bake | **動く**(baker.py が `scalar_rgb` を内部固定するため LLVM 不要) | +| sm-render | **クラッシュ**(scene_baseline.yaml の `variant: llvm_ad_rgb` が JIT 必須) | + +**解釈**: 過去のキャリブ作業時には何らかの方法で `DRJIT_LIBLLVM_PATH` が設定されていた(手動セットアップ/別シェル等)が,現在の Windows 環境では消えている.LLVM 自体は `C:\Program Files\LLVM\bin\` に残っていたため,**環境変数を再設定するだけ**で復旧可能と判明. + +**復旧手順**: + +```powershell +# User scope に永続化(1 度だけ) +[Environment]::SetEnvironmentVariable( + 'DRJIT_LIBLLVM_PATH', + 'C:\Program Files\LLVM\bin\LLVM-C.dll', + 'User' +) +``` + +> 注意: 既に起動済みのプロセスには反映されない.新規 PowerShell を開いた時点から有効化.本セッションの計測では各コマンド先頭で `$env:DRJIT_LIBLLVM_PATH = '...'` を明示設定して回避. + +**復旧確認**: + +``` +DRJIT_LIBLLVM_PATH: C:\Program Files\LLVM\bin\LLVM-C.dll +mi.variant(): llvm_ad_rgb +JIT activation: OK +``` + +#### 計測結果 + +**ベンチ環境**: Windows 11 Pro 22631 / PowerShell 5.1 / Intel HD Graphics 520 / 電源プロファイル「バランス」(High performance への変更は実施せず,TEST_04 全試行で同条件). + +**B1: sm-render**(`configs/scene_baseline.yaml`,`llvm_ad_rgb`,spp=1024,max_depth=8) + +| ラン | 時間 (s) | +| --- | --- | +| warm-up (run 0, 捨) | 524.09 | +| run 1 | 507.86 | +| run 2 | 502.32 | +| run 3 | 527.19 | +| **中央値** | **507.86 s ≈ 8.46 分** | + +範囲 502.32〜527.19 s(±2.4%),安定. + +**B2: path bake**(`configs/scene_baseline.yaml`,`--bake-mode path --bake-samples 16`,`scalar_rgb` 固定) + +| ラン | 時間 (s) | +| --- | --- | +| warm-up (run 0, 捨) | 52.54 | +| run 1 | 55.97 | +| run 2 | 65.48 | +| run 3 | 53.22 | +| **中央値** | **55.97 s** | + +範囲 53.22〜65.48 s(±10%),B1 より変動大.bake 自体が短時間で PyVista screenshot や I/O オーバーヘッドの寄与が相対的に大きいため. + +**出力ファイル ハッシュ・統計(数値同等性検証の基準値)**: + +| ファイル | SHA256 | サイズ | 統計 | +| --- | --- | --- | --- | +| `output/_bench/luminance.npy` | `D8B234BB…D4A17AF` | 2,097,280 B | shape=(512,512), float64, mean=147.693, std=46.158, max=233.626, min=0.0 | +| `output/_bench/bake.npz` | `0F28BC6F…BB3A4AA7` | 222,702 B | per-face irradiance, 全メッシュ | + +#### JIT 状態診断(最終) + +| 項目 | 値 | +| --- | --- | +| `mi.set_variant("llvm_ad_rgb")` | 成功 | +| `mi.variant()` 戻り値 | `llvm_ad_rgb` | +| `DRJIT_LIBLLVM_PATH` 環境変数 | `C:\Program Files\LLVM\bin\LLVM-C.dll`(User scope 永続化済み) | +| `jitc_llvm_init` 警告 | 出ない(child プロセスで `$env:DRJIT_LIBLLVM_PATH` を明示設定した場合) | + +#### 解釈 + +- **B1 中央値 507.86 s ≈ 8.46 分** が現状の sm-render 1 回の所要時間.これは「LLVM JIT 復元後」の値.JIT 復元前は実行不能だったので「効果無限大」とは言えるが,過去キャリブ時の値と等しいと推定(同条件のはず). +- **B2 中央値 55.97 s** は path bake samples=16 の値.samples=64 や 256 にすると線形に伸びると予想(baker.py のループ構造から). +- B1 と B2 で **9.1×** の差があるが,これは spp の差(1024 vs 16 per-face MC)と評価対象規模(512² 画像 vs 全メッシュ per-face)の違いによる.直接比較は意味なし.それぞれ独立に最適化対象. + +#### 学び + +1. **環境変数依存の脆弱性が露呈**: `DRJIT_LIBLLVM_PATH` 未設定で sm-render が即死する.`docs/02_ENV` か README に明記すべき.Speed-1 の方向性に影響. +2. **B1 を 3× 以上速くするには JIT を本物の wavefront 化(バッチ評価)が必要**: 既に `llvm_ad_rgb` 経路に乗っている以上,「JIT 有効化」自体は完了している.純粋な JIT 経路有効化だけでこれ以上速くなる伸びしろは少ない可能性(要検証). +3. **B2 の path bake は per-face Python ループが支配的**: samples=16 で 56 秒は十分速いが,samples を増やすと急激に伸びる.Speed-2(wavefront 化)の効果は samples 数に比例して大きくなる. + +#### 次のアクション + +Speed-1 の方向性を **再定義**: + +- 当初想定: 「LLVM JIT を有効化する → 自動的に数倍速くなる」 + → **既に LLVM JIT に乗っていることが判明**したため,純粋な「JIT 有効化」だけでは追加の高速化は得られない可能性大. +- 新方向: **「環境変数未設定でも自動 fallback する仕組み」+「JIT 経路で確実に走っていることをログで明示」** を Speed-1 として実装.これは速度自体は変えないが,再発防止・診断容易化の意味で価値あり. +- **本命の高速化レバーは Speed-2(path bake wavefront 化)に移る**.B2 を 10× 以上速くする道が残る.B1 は Mitsuba 内部の最適化が既に効いているので,追加の打ち手は限定的. + +--- + +### Speed-1: LLVM JIT 自動検出と診断ログ強化 (Robust JIT Activation) + +> **方向修正**: Speed-0 の調査で「LLVM JIT は復元後ベースラインに既に乗っている」ことが判明したため,本イテレーションは「JIT 有効化による高速化」ではなく「**環境破綻の再発防止+診断容易化**」に再定義する.純粋な実行時間短縮ではなく,**今後の試行を安全に進めるための土台整備**. + +- **日付**: 未実施 +- **コミット**: 未実施 +- **背景・問題意識**: Speed-0 計測前に判明したとおり,`DRJIT_LIBLLVM_PATH` 未設定だと sm-render が即死する.現在は User scope に永続化したが,新規 PC・別ユーザー・CI 環境で同じ問題が再発する.また「現在 JIT 経路に乗っているか」が見えにくく,scalar fallback で密かに遅くなっているケースを取り逃がすリスクがある. +- **仮説(技術的根拠)**: + - **(a) 自動検出**: `C:\Program Files\LLVM\bin\LLVM-C.dll` 等の標準パスを `mitsuba.set_variant` 前に Python 側で探索し,見つかれば `os.environ['DRJIT_LIBLLVM_PATH']` をプロセス内で設定する.これにより環境変数未設定でも JIT が起動する. + - **(b) 診断ログ**: `mi.set_variant` 成功時に「実際の variant」と「JIT backend の稼働状態」をログ出力.scalar fallback 時は明示的に警告する. +- **試した変更**: 未実施(実装予定): + - `src/sm_tias_lightsim/render/runner.py`: variant 設定前に LLVM-C.dll 自動探索ロジックを追加.候補パス: 環境変数 `DRJIT_LIBLLVM_PATH` → `C:\Program Files\LLVM\bin\LLVM-C.dll` → `C:\Program Files (x86)\LLVM\bin\LLVM-C.dll` → `LLVM_DIR/bin/LLVM-C.dll` 等.発見時に `os.environ` 更新. + - `src/sm_tias_lightsim/visualize/baker.py`: 同等のロジック(path bake は scalar_rgb 固定だが,将来 wavefront 化で LLVM 経路に乗るため統一). + - `docs/02_ENV/ENV_02_環境構築手順.md`: LLVM のインストール手順と `DRJIT_LIBLLVM_PATH` 設定を明記. + - テスト: LLVM-C.dll の探索ロジックを単体テスト(モックパスで Test-Path 相当を確認). +- **期待した効果**: + - B1 / B2 の **計測値は不変**(既に JIT 経路に乗っているため). + - 再現性向上:環境変数未設定の新環境でも自動復旧. + - 診断容易化:JIT 経路で走っていることがログから確認できる. +- **計測コマンド**: ベンチマーク条件参照(Speed-0 と同じ条件) +- **計測結果**: 未実施 +- **数値同等性**: 未確認(luminance.npy のハッシュが Speed-0 と一致すること) +- **解釈**: 未実施 +- **学び**: 未実施 +- **次のアクション**: 未定 + +--- + +### Speed-2: path bake wavefront 化 (Wavefront Bake) + +- **日付**: 未実施 +- **コミット**: 未実施 +- **背景・問題意識**: `src/sm_tias_lightsim/visualize/baker.py` の path bake は per-face で hemisphere モンテカルロ積分を回しており,`scalar_rgb` variant 固定.現状で「高 samples が非現実的」と CLAUDE.md にも明記されているように,最大のボトルネックの 1 つ. +- **仮説(技術的根拠)**: per-face ループを `Vector3f` バッチに置換し,`llvm_ad_rgb`(JIT 有効)で 1 回のベクトル化レイ評価に変換すれば,**10〜100×** の高速化が見込める.精度は不変(同じ式を別の評価戦略で解くだけ). +- **試した変更**: 未実施 +- **期待した効果**: B2 (path bake) で **10×** 以上.B1 (sm-render) には影響なし. +- **計測コマンド**: ベンチマーク条件参照 +- **計測結果**: 未実施 +- **数値同等性**: 未確認(bake.npz の face_values が ±5σ 以内) +- **解釈**: 未実施 +- **学び**: 未実施 +- **次のアクション**: 未定 + +--- + +## 終了条件 (Exit Criteria) + +以下のいずれかに到達したらこのドキュメントの初版(Speed-0〜Speed-2)を完了とする. + +- B1 (sm-render) が **3× 以上**速くなる,もしくは「JIT は既に走っており LLVM 経路に乗っている」ことが確認できる. +- B2 (path bake) が **10× 以上**速くなる,もしくは「wavefront 化に必要な前提(per-ray の独立性等)が破れているため不可」と判明する. +- 数値同等性が破れた最適化は不採用とする. + +それ以降の最適化(denoiser・サンプラ・クラウド GPU 等)は Speed-3 以降で別途検討する.