松田研究室
FindingID: p2-flag-revisit-sweep
Status: stable / task 保持 flag 全数再 gate sweep (2026-08-16 GPU 専有タスク)
← Findings Index
P2 · flag revisit · 全数再 gate

保持 flag 全数再 gate sweep — 8 維持 / 1 flip (loss_path -26.5%) + bench validate 抜けを発見

C0/S1/W1/W2/S2 でコスト構造が 5 段変わったことを受け、<code>BackendConfig</code> 全 16 field を機械走査して保持 variant を再判定。実測 9 件のうち <strong>8 件は verdict 維持</strong>、<strong>1 件 (<code>loss_path = "gpu"</code>) が flip</strong> — replay final regime で <strong>-26.5%</strong> (21.210 → 15.591 ms/iter、sync-tax 9.20 → 2.96)、iter5000 で -29.6%。残り 7 件は validate hard error による構造的非互換 / 禁忌リスト / harness 非対応で「判定不能」を理由付きで記録した。副産物として <code>splat bench</code> が <code>BackendConfig::validate</code> を呼んでおらず、<code>forward_submission="chained"</code> + <code>tile_sort="tile_counting"</code> のような無効組合せを <strong>exit 0 で黙って別経路実行</strong>していたことを発見し修正。

positiverank: highaccepted第 1 軸第 3 軸flag-revisitgate-sweeploss-pathbackend-configvalidateregression-guardlegostop-the-popdefault-flip
Δ Wallclock
loss_path flip: replay -26.5% (final) / -29.6% (iter5000)、12.5k gate -35.3% — ただし公式 config は既に gpu 明示のため公表値は不変 (hygiene flip)
Impact
BackendConfig 全 16 field を機械走査し、default 以外の variant を全数再判定。実測 9 件のうち 8 件は verdict 維持、1 件 (loss_path) が flip。loss_path = "gpu" は replay final regime 21.210 → 15.591 ms/iter (-26.5%) / iter5000 -29.6%、12.5k full gate (同一 session 交互 A/B、n=3) で 283.00 → 183.00s (-35.3%)・PSNR 36.142 → 36.188 dB (+0.047、guard ±0.1 内)。ただし この flip は公式数値を 1 つも動かさない hygiene — 全 237 config が loss_path を明示指定済みで 12.5k gate 系は例外なく "gpu"、enum default だけが 2026-04-30 以来実運用から取り残されていた。残り 7 件は validate hard error による構造的非互換 (5) / 禁忌リスト (2) / harness 非対応 (1) / 非 perf variant (3) として理由付きで判定不能を記録。副産物として splat bench の validate() 抜け (無効組合せが exit 0 で silent 別経路実行) を発見・修正した。
01

本文

2026-08-16 の 1 日で default スタックのコスト構造は C0 (resident binning) → S1 (pipeline 全域 resident) → W1 (warp sparse skip) → W2 (chained submission) → S2 (forward 1 CB 化) と 5 段変わった。`BackendConfig` の保持 variant はいずれもこれ以前の環境で verdict が付いており、規約 (敗者 variant も enum に残し、コスト構造が変わったら再判定する) に従って全 16 field を機械走査し、default 以外の variant を全数再判定した。判定は `splat bench` の fixed-workload replay (Lego final checkpoint 409,660 splats、warmup 20 / iters 200) で行い、有意閾値は harness calibration の規約どおり max(2σ, 1%)。

Headline (8 維持 / 1 flip、loss_path -26.5%)

実測できた 9 flag のうち 8 flag は verdict 維持、1 flag が flip。flip したのは loss_path で、enum default の Host に対し Gpu が replay final regime 21.210 → 15.591 ms/iter (-26.5%)、iter5000 regime 20.712 → 14.592 (-29.6%)。機構は GPU busy 56.6% → 81.0% / sync-tax 9.20 → 2.96 ms/iter が直接示す — submission = "chained" (W2) の Stage B (loss chain 1 CB 統合) は GPU loss 経路にしか効かない設計なので、loss_path = Host の default は W2 の主要部分を丸ごと取りこぼしていた。残り 7 flag は validate hard error による構造的非互換 (5)・禁忌リスト (2)・harness 非対応 (1)・非 perf variant (3) で判定不能とし、理由を enum doc と下表に記録した。

副産物: `splat bench` の validate 抜け (修正済み)

再判定の非互換確認中に、splat bench が BackendConfig::validate() を一度も呼んでいないことが判明した (呼んでいたのは train 側の FullConfig::validate のみ)。このため forward_submission = "chained" + tile_sort = "tile_counting" のような validate が hard error で禁じている組合せが exit 0 で通り、22.770 ms/iter という「もっともらしい数字」を吐いていた。実体は encode_forward_chained が use_tile_counting_sort を一切参照せず global radix を走らせていただけで、flag が silent に無視された default と同じ測定だった。これは validate が hard error として防ぐことを目的にしていた silent override そのもの。bench.rs の config load と --parity candidate 読み込みの 2 箇所に validate() を追加して塞ぎ、あわせて取り残されていた C3 bench 用 config 4 本 (S2 の default flip 時に train 側 config だけ修復されていた) に当時の実効値 forward_submission = "per_stage" / radix_scan = "cpu" を明示した。

1. 全 flag × Δ 表 (BackendConfig 全 16 field)

「default 以外の variant を持つか」で機械走査し、持つものは全て下表に載せた。判定 列の 維持 は再判定しても既存 verdict が変わらないこと、flip は default 交代、判定不能 は測定が原理的に取れないことを指す。Δ は replay final regime n=3、baseline は sweep 内 3 点の実行位置線形補間 (§3 参照)。

field再判定した variantΔ (final, n=3)σ閾値判定根拠
`loss_path``gpu`**-26.49%**2.12%1.92%**flip**12.5k gate 済 (§2)。W2 Stage B は GPU loss 経路専用
`emit_pairs``stop_the_pop`-0.05% (n=10)1.11%2.22%維持 (棄却)n=3 で -1.39% と閾値近傍 → n=10 に escalate して null 確定
`backward``original`+13.26%2.33%4.66%維持 (棄却)warp_any は Simd 専用のため W1 喪失分を含む合成 Δ
`backward``tg`+63.61%0.31%1.92%維持 (棄却)同上。禁忌 `!33c` だが依頼の明示指定で 1 判定のみ実施
`raster_backward_sparse``off`+16.21%0.17%1.92%維持 (敗退)W2/S2 後は busy 律速寄りで W1 の効きは gate 時 (-11.2%) より **拡大**
`raster_backward_range``full_range`+5.30%0.26%1.92%維持 (敗退)W1 が backward 定数コストを先に削ったぶん gate 時 (-14.98%) より縮小
`forward_submission``per_stage`+4.82%0.12%1.92%維持 (敗退)両 arm で hierarchical scan 固定 → **1 CB 化単独の寄与 ≈ -4.8%**
`submission``per_kernel`+3.59%0.54%1.92%維持 (敗退)gate 時 -13.7% から 1/4 に縮小 (S2 と回収先が一部重複)
`target_cache``false`(-0.70%)0.58%1.92%判定不能**harness 非対応** — bench は `train_step` 直叩きで target を事前 upload、flag が no-op
`tile_sort``tile_counting`———判定不能 (skip)validate hard error (S2 は global_radix 必須)。再判定仮説は falsified (§4)
`dispatch``batched_tail`———判定不能 (skip)validate hard error — S2 が A.7 の統合対象を包含し排他化
`radix_scan``cpu`———判定不能 (skip)validate hard error (S2 は per-pass host 往復を許さない)
`radix_scan``gpu` (F.3 flat)———判定不能 (skip)同上
`binning``per_iter_alloc`———判定不能 (skip)validate hard error (chained は resident arena 前提)
`emit_pairs``simd`———再判定せず**禁忌リスト** `!33b` SIMD prefix (禁忌はコスト構造変化の例外)
`forward``f16`———再判定せず**禁忌リスト** feat.G f16 forward
`shader_fast_math``false`———対象外perf variant ではなく IEEE 準拠 bit-repro 用 (設計上遅い)
`queue_reuse``false`———対象外documented no-op (M-3 で per-iter queue 経路は消滅)
`profile``true`———対象外計測用 instrumentation であって perf variant ではない
BackendConfig 全 16 field の再判定結果。実測 9 / 構造的非互換 5 / 禁忌 2 / 非 perf variant 3 / harness 非対応 1 (field 単位では 16、variant 単位では 19 行)。

2. flip した唯一の flag: `loss_path = "gpu"`

LossPathKind::Gpu の verdict は 2026-04-30 以来「検証中 (30k validation 未確定)」のまま据え置かれており、今日の 5 段のコスト構造変化をどれも通っていない唯一の flag だった。しかも SubmissionKind::Chained (W2、今日 default 化) の doc が明記するとおり Stage B (ssim → loss → backward → adam の 1 CB 連結) は GPU loss 経路にしか効かない。つまり enum default (Host) のままだと W2 の主要部分が無効化される状態が今日ずっと続いていた。

regimehost (enum default)gpu (候補)Δσ閾値判定
final (409,660 splats)21.210 ms/iter15.591**-26.49%**2.12%1.92%有意 (13.8x)
iter5000 (373,933 splats)20.712 ms/iter14.592**-29.55%**2.12%4.24%有意 (7.0x)
GPU busy (final)56.6%81.0%+24.4pp——機構
sync-tax (final)9.204 ms/iter2.961**-67.8%**——機構
GPU busy ms/iter (final)12.00712.605+0.60——GPU 実仕事はほぼ不変
loss_path replay A/B。busy ms/iter が +0.60 しか増えないのに wallclock が -5.6 ms/iter 縮む = 削れたのは純粋に同期税で、GPU 側の仕事は増えていない。

3. 方法論: baseline drift 2.46% と位置補間

sweep の冒頭 / 中間 / 末尾に同一 default baseline を 3 回挟んだところ 15.566 → 15.714 → 15.954 ms/iter と単調増加 (spread 2.46%) の thermal drift が出た。閾値 1.92% と同オーダーなので、pooled mean を基準にすると sweep 後半の arm が一律に不利化する。そこで各 arm の Δ は 実行位置による baseline の線形補間に対して算出した。影響が大きいのは後半に測った 2 件 (submission = per_kernel +3.59%、forward_submission = per_stage +4.82%) で、pooled baseline だと +4.4% / +7.1% と過大評価される。いずれも符号と結論は変わらないが、卒論に載る数字としては補間後を採る。

  • n=3 は screen、n=10 が確定: harness calibration の運用ガイド (gate 判定は n>=10 推奨) に従い、n=3 で閾値近傍 (|Δ| が閾値の 1/1.5 超) に落ちた stop_the_pop のみ n=10 へ escalate した。結果 n=3 の -1.39% は n=10 で -0.05% に収束し、ノイズだったことが確定 (両 arm を隣接実行して drift も抑えた)。
  • parity は 7 件実施し全 PASS: `bwd-original` / `bwd-tg` / `targetcache-off` / `sparse-off` / `range-full` / `sub-perkernel` / `fwdsub-perstage` で grad 5 種 (tol 1e-4) + `tile_offsets` byte 一致。`sorted_idx` は既知の tie-order 非決定性 (~0.2%) のため informational。
  • parity を skip した 2 件と理由: `stop_the_pop` は品質影響系 (数値同値性が成り立たない設計) のため規約どおり replay のみ。`loss_path` は `--parity` が GPU loss 経路専用で host 側を比較できないため 構造的に parity 不能 — 品質証拠は 12.5k の PSNR 対比のみで、bit-exact 系の他 flag と証拠の質が違う点は明記しておく。

4. 再判定仮説が falsified された 2 件

  • `tile_sort = "tile_counting"` (C3): 「敗因だった CPU scan 同期が S2 の hierarchical scan 環境で消えた可能性」という仮説は 成り立たない。S2 の hierarchical scan が GPU 化したのは radix histogram の prefix scan (整数和なので block 分割に依存せず bit-exact 化できた) であって、C3 が要求する per-tile count → exclusive scan → scatter の host 同期ではない。後者は tile 境界の確定に host 介在が要るため S2 の 1 CB forward と原理的に両立せず、`validate` が hard error にしている (実測確認済み)。加えて per-tile bitonic の O(n log²n) 劣位も不変。
  • `dispatch = "batched_tail"` (A.7): 「chained submission との相互作用が未計測」という動機は、相互作用の余地ではなく機能重複による排他化だった。S2 は A.7 が統合対象にしていた extract_offsets + rasterize を既に同一 CB に含んでおり、`validate` が「S2 subsumes the A.7 batched tail」として hard error にする。a-7 の scene 依存 -1.6〜-18.6% は S2 未導入時の値として保存する。

5. 再判定で判明した既存 verdict の帰属訂正

  • W2 と S2 は「直交」ではなく利得が一部重複する: W2 gate は per-kernel 帰属 (`ts_chain_commit_wait` が S2 前後で不変) から両者を直交と記述したが、default 交代の利得としては重複する。S2 後に `submission = per_kernel` へ戻した Δ は +3.59% で、W2 gate 時の -13.7% の約 1/4 しかない。S2 が forward 側の CB/wait を先に畳んだぶん、W2 が回収できる残りの同期税が減ったため。
  • S2 の「1 CB 化単独の寄与」が測れた: S2 gate は forward 1 CB 化と hierarchical scan をセットで A/B したため単独寄与が未計測だった。本 sweep は両 arm で `radix_scan = "gpu_hierarchical"` を固定して `forward_submission` だけを振っており、1 CB 化それ自体は約 -4.8%、残り (gate 全体 -12.3% との差) は hierarchical scan 側と分解できる。per-stage 経路でも hierarchical が実際に走ることは `radix_sort_core` の分岐で確認済み (silent fallback なし)。
  • W1 の効きは gate 時より拡大した: `raster_backward_sparse = off` の Δ は +16.21% で、W1 gate 時の -11.2% より大きい。W2/S2 が同期税を削って GPU busy 律速 (busy 81%) に寄った結果、GPU 実行時間を削る最適化の相対価値が上がったため。逆に `raster_backward_range = full_range` は +5.30% と gate 時 (-14.98%) より縮んでおり、W1 が backward の定数コストを先に削ったぶん range 打ち切りの取り分が減ったことを示す。

6. 関連

  • flag 定義と verdict 3 点セット: splat/crates/splat-train-v1/src/config.rs (各 enum に「2026-08-16 S2 後再判定」行を追記)
  • bench validate 修正: splat/crates/splat-cli/src/cmd/bench.rs (`BenchTomlConfig::from_path` + `run_parity`)
  • 取り残されていた C3 bench config の修復: splat/configs/2026-08-16-c3-bench-*-tile_counting.toml / 2026-08-16-c3-parity-candidate.toml
  • harness 規約 (σ / 閾値 / n の運用): docs/findings/p2-bench-harness-calibration.toml
  • BackendConfig 規約: docs/architecture/backend-and-compiler-conventions.md
  • 禁忌リスト: docs/strategy/2026-08-msplat-gap-sweep.md 大原則 4

7. loss_path 12.5k full gate (同一 session 交互 A/B、n=3)

armr1r2r3meansdmedian
host wallclock [s]265.0262.0322.0**283.00**33.81265.0
gpu wallclock [s]179.0186.0184.0**183.00**3.61184.0
host PSNR [dB]36.17636.10136.148**36.142**0.03836.148
gpu PSNR [dB]36.11436.24036.211**36.188**0.06636.211
12.5k full gate。wallclock mean -35.3% / median -30.6%、PSNR +0.047 dB (guard ±0.1 内)。host r3 (322s) が外れ値で host 側 sd が 33.8s と大きい (gpu は 3.6s) ため median も併記したが、結論は不変。
この flip は公式数値を動かさない (hygiene flip)

splat/configs/ の 全 237 config が loss_path を明示指定しており、default 依存の config は 0 件。とくに卒論に載る 12.5k gate 系 (C0/S1/W1/W2/S2 の *-12500-*.toml) は例外なく loss_path = "gpu" を書いていた。したがって本 flip で挙動が変わる既存 run は 1 つも無く、公表済み wallclock / PSNR は一切変更されない。変わるのは「config で明示しなかった場合の既定値」だけであり、その意味でこれは性能改善の主張ではなく enum default を実運用の実態に揃える hygiene である。逆に言えば、default が Host のままだと W2 Stage B を取りこぼした構成が「既定」として提示され続けるという実害があった。

品質証拠の質は他の default flip と異なる

C0 / W1 / W2 / S2 の default flip はいずれも bit-exact 主張を伴い、bench --parity や単体 fixture の byte equality で裏付けられていた。loss_path は違う — host と GPU で SSIM の計算経路そのものが異なり、しかも --parity は GPU loss 経路専用なので 構造的に parity 比較ができない。品質証拠は 12.5k の PSNR 対比 (Δ +0.047 dB) のみである。補強として既存の Lego 12.5k / loss_path = Gpu の run 19 本が PSNR 36.183 ± 0.045 dB の帯を成しており、本 gate の host arm (36.142) / gpu arm (36.188) はいずれも帯の内側。なお phase5-step31-x-gpu-loss.md はこの比較で n=1 の PSNR -0.65 dB regression を報告し 4-sample variance test で撤回した経緯がある — 「撤回」は差が無いことの証明ではないので、n=3 の spread (host sd 0.038 / gpu sd 0.066 dB) まで見て guard 内と判断した。

8. 計測衛生 (自己申告)

本タスクは GPU 専有条件で実施したが、作業中に 2 回この条件を自分で破った: (1) validate 制約の網羅確認のため committed config を全件 `splat bench` に通したところ、これが実際に bench を実行し 12.5k gate の `gpu-r1` と競合した。(2) `cargo test` を gate 実行中に走らせ `host-r2` と競合した。とくに (2) は host loss 経路が host 側 SSIM で CPU 律速であるため、CPU 競合が host arm の wallclock を膨らませ 「gpu が速い」という自分の仮説に有利な方向にバイアスする。両 run は無効として破棄し、全 job 停止後に単独で取り直した clean run で置き換えた (上表の r1 host 側以外はすべて clean)。以後の validate 網羅確認は GPU を使わない静的 TOML 解析で行い、全 237 config が制約を満たすことを確認した。

02

関連する run

この finding が観測された / 言及している実験 run。

03

関連 finding

© 2026 大竹律輝 — 松田研究室