Newer
Older
SmTIAS-LightSim / docs / 06_TEST / TEST_19_sppと計算時間ノイズ指標安定性.md

spp と計算時間・ノイズ・指標の安定性 (Samples per Pixel vs Time, Noise, and Metric Stability)

TEST_18 までのレンダは spp=1024 固定で,大きいキャビティほど生の輝度が低く相対ノイズが 7〜26% に達していた(指標はノイズ補正で救っている).研究室サーバの GPU で 1 条件 5 秒に なったので,spp を 256〜8192 で振り,(1) 計算時間のうち GPU が何秒か,(2) ノイズが 1/√spp で下がるか,(3) 各指標がどの spp で安定するかを測って今後の標準 spp を決めた (2026-09-14).結論: GPU 時間は spp に厳密に比例し固定費は 0.8 秒.ノイズは 1/√spp 則に 正確に乗る.構造 CoV は 1024 で十分,画像全体 min/max 比を暗い条件で比べるなら 2048〜4096.

関連:

実験条件 (Setup)

  • 条件: TEST_18 の 6 条件の YAML を流用(spp と seed だけ書き換え).球 φ340 の軸上と θ=90°, 立方体 L=234 の軸上と θ=90°,ノイズが最も大きい球 φ500 θ=90° と立方体 L=340 θ=90°. 1 灯・板向き・バッフル付き,旧材質(ρ=0.85 blendbsdf),512²,max_depth=16
  • spp: 256 / 512 / 1024 / 2048 / 4096 / 8192(2 倍刻み)× seed 2 つ=72 レンダ.16384 は ユーザー都合で未実施(12 レンダ・約 17 分)
  • 計測: 段階別の壁時計(YAML 読込 / PLY 書き出し / シーン読込 / mi.render / 保存 / 評価). mi.render は dr.sync_thread() で GPU の完了を待ってから測る(投げっぱなしで短く見える ことを防ぐ).GPU 率 = mi.render ÷ 全体
  • 指標: 残差ノイズ CoV(生 − 平滑化)・構造 CoV・輪帯平均 min/max・画像全体 min/max (ノイズ補正あり/なし)・ノイズ場の極値
  • 環境: Newton GPU 0(RTX A6000)・cuda_ad_rgb・mitsuba 3.7.1・SM_DRJIT_THREADS=16・逐次実行

結果 1 — 計算時間: GPU は spp に比例,固定費は 0.8 秒 (Time)

6 条件 × 2 seed の平均.

spp全体 sGPU(mi.render)sCPU 固定費 sGPU の割合
2562.01.20.860%
5123.22.50.876%
10245.95.10.887%
204811.110.30.893%
409620.920.10.896%
819240.639.80.798%
  • GPU 時間は spp に厳密に比例(1024 spp あたり 5.0 秒.条件による差は ±10%.球がやや遅い)
  • 固定費は 0.75〜0.8 秒で spp に依らず一定.内訳は PLY 書き出し 0.34 秒・評価(図なし)0.29 秒・ 保存 0.12 秒・YAML 読込とシーン読込(OptiX の BVH 構築を含む)は各 0.01 秒
  • spp ≥ 1024 で固定費は 1 割以下.CPU 側をこれ以上削る意味は薄い.256 では 4 割を占めるので, 低 spp を多数回す用途なら筐体メッシュの PLY キャッシュが効く

結果 2 — ノイズは 1/√spp 則に正確に乗る (Noise)

条件生 meanノイズ CoV(1024)ノイズ × √spp(6 段階の範囲)
球 φ340 軸上0.3550.0922.93〜2.99
球 φ340 θ=90°0.3230.1454.63〜4.67
立方体 L=234 軸上0.3870.1043.30〜3.32
立方体 L=234 θ=90°0.3560.1564.97〜5.08
球 φ500 θ=90°0.1530.1895.84〜6.05
立方体 L=340 θ=90°0.1740.2006.23〜6.38
  • ノイズ × √spp は全条件で ±1〜2% 以内で一定=MC ノイズだけで,レンダ側に別のノイズ源は無い
  • ノイズ量は生の輝度で決まる(暗いほど大きい)が,同じ明るさでも軸上より θ=90° が 1.5 倍大きい (オフ軸は一次照射キャップの経路分散が大きい).大キャビティを球 φ340 軸上と同じノイズにするには spp を 4〜5 倍要る
  • 画像全体 min/max のノイズ補正量(ノイズ場の max − min)も 1/√spp で減り,8192 で平均の 1% 以下

結果 3 — 指標の安定性 (Metric Stability)

spp_noise.png 下段.誤差棒は seed 2 つの差の半分.

指標1024 での状態安定する spp
構造 CoV256→1024 で 5〜15% 低下後ほぼ一定.seed 差 ≤0.00051024 で十分(8192 との差 ≤0.002)
画像全体 min/max(補正あり)明るい条件は安定(seed 差 0.003).暗い φ500・L=340 は 0.93〜0.94 で seed 差 0.012048〜4096(暗い条件が 0.95〜0.96 に収束し seed 差 0.002)
画像全体 min/max(補正なし)どの条件も spp とともに上昇し続ける8192 でも収束しない(ノイズ補正は必須)
輪帯平均 min/maxθ=90° で 0.97〜0.99 に張り付き,seed 差 0.003〜0.01spp では改善しない(方位平均の問題)
  • spp=1024 は構造 CoV には十分だが,画像全体 min/max 比は暗い条件で 0.01〜0.02 過小評価していた (TEST_18 の min の値のうち球 φ500・立方体 L=340 はその分だけ低めに出ている.順位は変わらない)
  • 補正なしの平滑化 min/max は spp を 32 倍にしても収束せず,補正の必要性を裏付ける

追試 — LED を軸上にそろえた 6 形状での計算時間 (Follow-up: Six Shapes)

発表スライドで「6 種類の形状の平均」と書くと,上の 6 条件は実際には 4 形状 × LED 位置 2 通り (θ=0°/90°)の混在なので説明と合わない.そこで LED を θ=0°(軸上)にそろえ,形状だけを 6 種類に 変えて計算時間を測り直した(2026-10-05).

  • 形状: 球 φ270・φ340・φ500(r=135/170/250)+ 立方体 L=187・L=234・L=340.上下で同じ内面積の組 (TEST_18 の対応).φ は球の内径,L は立方体の一辺 mm
  • それ以外(1 灯・板向き・バッフル付き・旧材質・512²・max_depth=16・spp 256〜8192 × seed 2・ Newton GPU 0・逐次)は本編と同じ.72 レンダ
  • sweep_spp_noise.py --set shapes6 で実行.出力は output/spp_noise_shapes6/(本編の結果は上書きしない)

平均±標準偏差(n=12=6 形状 × seed 2).

spp全体 sGPU(mi.render)sCPU 固定費 sGPU の割合
2561.9±0.31.2±0.10.8±0.260%
5123.1±0.22.4±0.20.7±0.177%
10245.7±0.55.0±0.40.7±0.188%
204810.7±1.110.0±1.00.7±0.193%
409620.4±1.919.7±1.90.7±0.197%
819240.1±3.239.4±3.10.7±0.198%
  • 本編の結論はそのまま成り立つ: GPU 時間は spp に比例(1024 で 5.0 秒),固定費は 0.7〜0.8 秒で一定
  • GPU 時間の標準偏差は平均の 8〜10%.ばらつきのほとんどは球と立方体の差で,球が立方体より 15〜20% 遅い(1024 で球 5.3〜5.5 秒・立方体 4.6〜4.7 秒).同じ形状ならサイズを変えても時間は ほぼ変わらない(立方体 L=187〜340 で 4.58〜4.67 秒).球のメッシュの三角形が多いことが一因と考えられる(未検証)
  • スライド用に 6 形状の 3D 配置図(shapes6_geometry_panel.png)とレンダ結果(shapes6_render_panel.png, spp=8192)を 2×3 で並べた図を作った.配置図は各形状が自動で拡大されるので,サイズの違いはラベルで示す

結論と推奨 (Conclusions)

  • 標準 spp: 構造 CoV・方位フーリエ・重心で比べる実験は 1024 のまま(5.9 秒/条件).画像全体 min/max 比を暗い条件(生 mean < 0.2)まで含めて比べる実験は 2048〜4096(11〜21 秒/条件. 255 条件で 50〜90 分)
  • CPU 側の最適化はここまで.固定費 0.8 秒は spp ≥ 1024 で 1 割以下
  • ノイズは 1/√spp 則に乗るので,必要な spp は「目標ノイズ ÷ 1024 でのノイズ」の 2 乗で見積もれる

限界・注意点 (Limitations)

  • 16384 は未実施.傾向は 8192 までで単調に収束しているため結論は変わらない見込み
  • nvidia-smi のサンプリングは,ジョブ再起動時の pkill がサンプラー自身を止めたため記録が無い. GPU 時間は dr.sync_thread() で同期した実測で取れているので結論には影響しない
  • 条件は 6 つ(1 灯・板向き).多灯やバッフル無しは未測定だが,ノイズは生の輝度で決まるので 同じ関係が成り立つはず
  • 時間は逐次実行の値.--workers 2 では 1 条件あたり 1 割ほど短くなる(ENV_04)

失敗パターン・方法論の学び (Pitfalls and Methodology)

  • mi.render の時間は同期してから測る.cuda variant では非同期に GPU へ投げられるので, dr.eval + dr.sync_thread() を挟まないと数十 ms に見える
  • サーバへの push は --only scripts だけだと足りないことがある.新しい src モジュール (evaluation/fullimage.py)を使うスクリプトは,全体を push してから回す
  • 併走プロセスの pkill -f は再起動時に自分も殺す.サンプラーを再起動するなら先に止めてから 起動する順序を守るか,PID ファイルで管理する

再現コマンド (Reproduction)

# YAML 生成(TEST_18 の _tmp_led_placement を流用するので先に sweep_led_placement.py --prepare-only)
uv run python scripts/sweep_spp_noise.py --prepare-only

# サーバで実行(GPU 0).spp を絞るなら --spps 256 512 1024
uv run sm-remote push
uv run sm-remote run --name spp --gpu 0 --threads 16 -- python scripts/sweep_spp_noise.py
uv run sm-remote pull spp_noise_sweep

# 解析(図と表)
uv run python scripts/build_spp_noise_comparison.py

出力: output/spp_noise_sweep/(レンダ別 72 ディレクトリ + summary.csv + spp_summary_table.csv + spp_noise.png).

追試(6 形状):

# YAML 生成(本編と同じく _tmp_led_placement が前提)
uv run python scripts/sweep_spp_noise.py --set shapes6 --prepare-only

# サーバで実行(_tmp は push 対象外なので --include で送る)
uv run sm-remote push --include configs/_tmp_led_placement --include configs/_tmp_spp_noise_shapes6
uv run sm-remote run --name shapes6 --gpu 0 --threads 16 -- python scripts/sweep_spp_noise.py --set shapes6 --spps 256 512 1024 2048 4096 8192
uv run sm-remote pull spp_noise_shapes6

# 配置図の撮影(6 形状.c = sphere_d270 sphere_d340 sphere_d500 cube_L187 cube_L234 cube_L340)
uv run sm-visualize --scene configs/_tmp_spp_noise_shapes6/scene_${c}_th000_spp1024_s0.yaml --no-bake --style slide --screenshot output/spp_noise_shapes6/geometry/${c}.png

# 表(平均±標準偏差)とパネル図
uv run python scripts/build_spp_shapes6_summary.py

出力: output/spp_noise_shapes6/(レンダ別 72 ディレクトリ + summary.csv + spp_time_table_mean_sd.csv + shapes6_geometry_panel.png + shapes6_render_panel.png + geometry/).

参照 (References)