docs/findings/p3-c2-bubble-attribution.toml §6 施策 #5 — refine tick (100 iter に 1 回) の CPU compact drain が 12.5k で 3.0〜3.8s (2.4〜3.1%) を占めることから、tick 頻度を半減すれば drain も半減し wallclock -1.2〜-1.5% を期待した hyperparameter 実験。<strong>12.5k n=3 交互 A/B で PSNR Δ -0.421dB (guard `on mean >= off mean - 0.05dB` を約 8.4 倍超過) — 不採用</strong>。wallclock 自体は Δ -25.6% と大幅に短縮したが、これは drain 削減 (メカニズムは的中、sync_iters 121→61 で確認、寄与は期待帯 -1.2〜-1.5% 相当) ではなく、tick 頻度半減が同時に densification 予算を削り最終 splat 数を -35% (407.7k→266.7k) 減らしたことによる副作用が主因 — <code>refine.every</code> は drain のみを制御する独立ノブではなく、tick cadence に紐づく growth/clone/split イベント数と opacity decay 累積量を同時に変える hyperparameter であることが判明した。<strong>default config は変更しない、採否はユーザー判断待ち</strong>。
[refine] every 100→200 に変更する hyperparameter 実験 (非 bit-exact、学習 dynamics が変わる)。12.5k Lego n=3 交互 A/B (off=every100 baseline / on=every200 candidate、他の refine パラメータ (stop_iter 等) は不変) で、PSNR guard (n=3 で on mean >= off mean - 0.05dB) と最終 splat 数の変化を主眼に計測した。PSNR Δ -0.421dB で guard を約 8.4 倍超過 — 不採用。wallclock は Δ -25.6% と大幅短縮したが、tick drain 半減 (sync_iters 121→61、期待帯 -1.2〜-1.5% 相当) は寄与のごく一部に過ぎず、大半は densification 予算削減による最終 splat 数 -35% (407.7k→266.7k) の副作用。refine.every は tick drain の独立ノブではなく、growth/clone/split イベント頻度と opacity decay 累積量 (`opacity_decay_rate` は refine cadence で適用) を同時に変える hyperparameter であることが判明した。r2 pair は事前登録条件 (load spike AND 3σ超) を満たし 1 回 retry したが、PSNR guard の判定には影響しない (PSNR は決定論的、load は wallclock のみに影響)。default config の書き換えはしない — 採否はユーザー判断待ち。§6 施策 #5 は「refine tick の CPU compact drain (12.5k で 3.0〜3.8s、2.4〜3.1%) は tick 頻度に比例するはずだから、頻度を半減すれば drain も半減し wallclock -1.2〜-1.5% を稼げる」という比較的単純な仮説だった。実測は wallclock こそ大幅に短縮したが、それは狙った効果ではなく、refine.every が tick drain と同時に densification 予算・opacity decay 累積量も支配する hyperparameter だったための副作用であり、PSNR guard を大幅に割り込んだ。不採用、default は変更しない。
| arm | run | train elapsed (s) | PSNR (dB) | final splats | run 窓内 load1 |
|---|---|---|---|---|---|
| off | off-r1 | 125.24 | 36.131 | 407664 | 1.11〜3.87 (正常) |
| on | on-r1 | 93.58 | 35.770 | 266474 | 1.83〜5.90 (正常〜やや上昇、判定閾値 6.0 未満) |
| off | off-r2 | 129.65 | 36.241 | 408855 | **汚染: 2.4〜6.08 spike。retry (132.69s) はさらに悪化 (12.78〜14.33 spike) — 2 回とも汚染、protocol 上 retry は 1 回のみのため元値を採用** |
| on | on-r2 | 93.72 | 35.736 | 267959 | **retry 値を採用 (2.18〜3.44、clean)。原系列 (114.02s) は load1 最大 16.97 の重度汚染で棄却** |
| off | off-r3 | 124.60 | 36.098 | 407920 | 1.09〜3.43 (正常) |
| on | on-r3 | 94.89 | 35.701 | 265540 | 0.68〜1.13 (正常) |
| **mean (n=3)** | **off** | **126.497** (σ 2.75, 2.17%) | **36.157** | **408146** | off-r2 は load 汚染 2 回とも解消できず、wallclock は参考値扱い |
| **mean (n=3)** | **on** | **94.063** (σ 0.72, 0.76%) | **35.736** | **266658** | on-r2 は retry で clean 値に置換済み |
| **Δ** | — | **-25.6%** | **-0.421** | **-34.67%** | — |
| pair | off PSNR | on PSNR | Δ |
|---|---|---|---|
| r1 | 36.131 | 35.770 | -0.361 |
| r2 (元値のみ、off/on とも original) | 36.241 | 35.697 | -0.544 |
| r2 (on のみ retry 値に置換、off は元値のまま — 本 finding 採用値) | 36.241 | 35.736 | -0.505 |
| r3 | 36.098 | 35.701 | -0.397 |
| **mean (全て元値)** | **36.157** | **35.723** | **-0.434** |
| **mean (r2-on を retry 値に置換、本 finding 採用値)** | **36.157** | **35.736** | **-0.421** |
guard は「n=3 で on mean >= off mean - 0.05dB」。実測 Δ は -0.421dB で guard を約 8.4 倍超過し、3 pair 全てで一貫して on < off (-0.36〜-0.55dB) — 単一 run のノイズではなく系統的な劣化。同一 config (off-r2) を 2 回実行した際の PSNR 差 (36.241 → 36.137、Δ0.104dB) が本実装のノイズフロアの目安になるが、観測された on/off 差はその 3.5〜5 倍あり、ノイズでは説明できない。wallclock の大幅な短縮 (Δ -25.6%) はこの PSNR 劣化とセットの副作用であり、単独の高速化施策として採用することはできない。
| 項目 | 内容 |
|---|---|
| 変更していないもの | `[refine] stop_iter` / `opacity_reset_every` / `grad_threshold` / `size_threshold` / `opacity_min` / `split_scale_factor` / `reset_opacity_val` / `max_scale_cap` / `enable_mcmc_respawn` — 全て final-12500 base と同一。差分は `[refine] every` (100→200) の 1 field のみ (`splat check` で 6 config 全て deserialize/validate 済み) |
| default config | **書き換えていない**。`splat-train-v1/src/config.rs` の `RefineConfig::default()` (`every: 100`) は本 gate では一切変更していない — 採否はユーザー判断待ち |
| code 変更 | **一切なし**。config ファイル 6 本 (`splat/configs/2026-08-30-re200-12500-{off,on}-r{1,2,3}.toml`) と retry 用の使い捨てヘルパー script (`splat/scripts/re200-retry-r2.sh`) のみを新設。`splat/crates/` 配下の src は無変更 |
| §6 施策 #5 の再評価が必要な場合 | 本 gate は「drain だけを削る」という前提が成立しないことを示した。候補メカニズムは (a) growth 発火機会が tick 回数 (12500 iter で 121→61 回) に直接律速される (`refine.rs:280,347-352,404`)、(b) `opacity_decay_rate` が refine cadence で累積適用される (`config.rs:196-200`) の 2 つで、本 gate はどちらが支配的かを切り分けていない。仮に再挑戦するなら、(a) 対策として growth の発火機会を iteration 数ベースに正規化する、(b) 対策として `opacity_decay_rate` を tick 頻度の逆数でスケールし累積 decay 量を固定する、の両方を独立に試し、最終 splat 数を baseline (~408k) に固定した状態で drain 削減の純効果 (期待 -1.2〜-1.5%) だけを分離計測できて初めて §6 の仮説を検証したことになる。現状の finding はその前提が崩れていることの記録であり、次の一手は別 task として起票する |