松田研究室
FindingID: p2-s1-pipeline-resident
Status: stable / task S1 pipeline 全域 resident 化 worktree 統合 + GPU gate (2026-08-16 GPU 専有タスク)
← Findings Index
P2 gap sweep · S1 GPU gate · 採用

S1 pipeline 全域 resident 化 — replay bench -22.9% (final regime) で採用 (Tier A/B/C)

worktree (<code>worktree-agent-afb59d93b2c731864</code>) で実装済みの S1 (pipeline 全域 resident 化: Tier A resident work buffers / Tier B ForwardState Buffer handle + *_from_buf 直結 / Tier C zero_grads スコープ化 + AdamUniforms 統合) を main へ統合し GPU gate を完遂。C3 統合 (32070c4) との conflict は tile_bin.rs を手 merge し、C3 (rejected flag) 併用時は S1 buffer 直結を legacy 経路へフォールバックさせる regression test 込みで解決。fixed-workload replay bench で <strong>final regime 28.630→22.059 ms/iter = -22.9%</strong> / iter5000 regime -21.9% (閾値 max(2σ,1%) の 10 倍超の有意差)、attribution 計測で alloc 成分の消滅 (ts_raster_fwd_alloc 0.2 µs/call 等) を確認。12.5k full gate は rep1 PSNR 36.051 dB が guard 外に出たため n=3 escalation → rep2 36.168 / rep3 36.224 dB で tail variance と判定し PASS。wallclock は 12.5k rep mean 261.55s (rep1 272.36 / rep2 257.55 / rep3 254.73s、公式 336.33s 比 -22.2%) で replay 判定と整合。<strong>採用 — flag なしの無条件 default</strong>。msplat 同日等価 gap は 2.10× → <strong>1.56×</strong>。

positiverank: highadopted-unconditional-no-flag第 1 軸第 3 軸gap-sweepphase-2s1residentalloc-auditunified-memorygpu-gateadoptedbench-harnesslegoattribution
Δ PSNR
12.5k full run PSNR guard: 基準 36.19 前後 (歴代同 recipe 7 run 分布 36.138-36.226) に対し rep1 36.051 (-0.14、guard 外) / rep2 36.168 / rep3 36.224 dB → n=3 mean 36.148 dB = -0.04 dB (±0.1 dB guard 内、PASS)。rep1 は歴代最低値だが S1 は数学的同値 (parity test 群で証明) のため run 分散の tail と判定
Δ Wallclock
replay bench final regime n=3: 28.630 → 22.059 ms/iter = **-22.9%** (閾値 max(2σ,1%)=2.05%)。iter5000 regime n=3: 26.113 → 20.405 ms/iter = **-21.9%** (閾値 1.29%)。12.5k full run: 公式 336.33s → rep1 272.36s / rep2 257.55s / rep3 254.73s = mean 261.55s (**-22.2%**)
Impact
別 worktree で実装済みだった S1 (pipeline 全域 resident 化) を main へ統合。C3 統合後の tile_bin.rs と conflict したため手 merge し、C3 (rejected flag) との新規相互作用 (S1 の buffer 直結が C3 の panic guard に当たる) はフォールバック + regression test で解決。build warning 0、MSL smoke compile (adam.metal binding 変更) + 新規 S1 test 9 本 (resident byte-stability / grow path / ForwardState parity / Vec vs raw parity / C3 fallback) 含む workspace 全 test pass。replay bench は final regime -22.9% / iter5000 -21.9% と Phase 2 単一項目として C0 に次ぐ効果で、attribution 計測 (S1 で新設した DispatchAttribution 4 点) が alloc 成分の消滅を直接証明 — C0 の「主犯は first-touch page fault」結論の pipeline 全域への一般化。12.5k full gate は PSNR rep1 が guard 外 (36.051) に出たが n=3 escalation で tail variance と確定 (rep2 36.168 / rep3 36.224、歴代同 recipe 分布 36.14-36.23)。採用 — flag なしの無条件変更として default 化。
01

本文

C0 (finding: p2-c0-resident-binning) は binning 経路の per-iter alloc を resident arena 化して -48.4% を得たが、pipeline の残り (project / rasterize forward / rasterize backward / project_backwards / adam) には per-iter fresh-alloc (~46MB/iter) と host Vec 往復 (~57MB/iter) が残っていた。別 worktree (worktree-agent-afb59d93b2c731864、分岐元 b053e35) で先行実装されていた S1 (Tier A/B/C の 3 層 + DispatchAttribution 計測 4 点) を main へ統合し、GPU gate を完遂した。

1. S1 の内容 (3 Tier)

Tier内容撤廃対象
A (resident work buffers)`GpuProjector` の出力 (splats2d/depths)、`Rasterize` の forward 出力 (out/final_t/last_contrib) と backward splats_grad を struct 保持の resident buffer に変更 (capacity-grow のみ、`ssim.rs::ensure_work_buffers` と同型)。memset は backward grad の active 範囲 (`n*9*4`) のみ~46MB/iter の fresh-alloc + first-touch page fault (C0 が binning で実証した主犯の一般化)
B (Buffer handle 直結)`ForwardState` に `splats2d_buf` / `sorted_idx_buf` / `tile_offsets_buf` / `final_t_buf` の handle (arena buffer の retain) を保持し、backward 系を `backward_from_buf` / `dispatch_from_buf_active` に直結。非 batched 経路 (per_stage default) も `backward_rasterize_buf_raw` → `project_backwards_from_buf_active` で splats_grad の Vec→GPU re-upload を撤廃。BatchedTail 経路の「buffer を作っても捨てていた」未完成部も修正~57MB/iter の host Vec → GPU 再 upload (splats2d 最大 ~14.7MB/枚 ほか)
C (小物 alloc + memset)`zero_grads` のクリア範囲を capacity → active num_splats に縮小 (12.5k 規模で ~59% memset 削減、`ts_zero_grads` として計測化)。`adam_step` の 6 scalar buffer を `AdamUniforms` 1 struct に統合 (5 group × 6 → 5 alloc/iter、adam.metal の binding 変更)30 小 alloc/iter + capacity 全域 memset

2. 統合作業 (C3 conflict の手 merge)

項目内容
worktree`worktree-agent-afb59d93b2c731864` (分岐元 b053e35)。main は C3 統合 (32070c4) + docs (e4db3f4) の 2 commit 先行
conflicttile_bin.rs のみ (C3: dispatcher + per-tile kernels / S1: `resident_tile_offsets_buf` accessor)。他 7 ファイルは `git apply` がそのまま通った
C3 相互作用 (手 merge で発見・解決)S1 の buffer 直結 forward は `resident_sorted_bufs()` を呼ぶが、C3 経路の sorted idx は arena の idx_a/idx_b ではなく別 buffer (idx_c3) にあり、C3 の panic guard に当たる (pre-S1 は per_stage + C3 が有効な組み合わせだった)。`GpuTileBinner::last_sort_used_c3()` accessor を追加し、C3 iter は buffer 直結を諦めて legacy host-slice forward にフォールバック (pre-S1 と同一挙動)。regression test `forward_state_c3_tile_counting_falls_back_to_host_slice_path` を追加
MSL smoke compileadam.metal の binding 変更 (buffer(4..9) → `AdamUniforms` struct buffer(4)) を `cargo test -p splat-metal adam` (= `Adam::new` + `device_compiles_adam_metal`) で検証、一発 PASS
testS1 新規 test 9 本 (project 2 / rasterize 3 / trainer 3 + C3 fallback 1): resident byte-stability (repeat call bit-exact) / grow path (img_size・num_splats 増減) / ForwardState buffer handle と host Vec の bit-exact parity / `backward_rasterize_buf` Vec 版 vs raw Buffer 版 parity。workspace 全 test pass、`cargo build --release` warning 0

3. replay bench A/B (final + iter5000 regime、各 n=3)

統合前に同一 machine/同日で baseline を取り直し (`final-pre` 28.630 ms/iter は calibration headline 28.312 ms/iter と 1.1% 差 = σ 圏内で整合)、S1 適用 build で同一 config を再計測した。S1 は flag なしの無条件変更のため、pre/post の差分は build のみ。

regimenvariantmedian ms/iterσ_pctdelta閾値 max(2σ,1%)判定
final (407,267 splats)3pre (e4db3f4)28.6301.02%———
final3post (S1)22.0590.22%**-22.95%**2.05%**有意 (採用)**
iter5000 (373,933 splats)3pre (e4db3f4)26.1130.19%———
iter50003post (S1)20.4050.64%**-21.86%**1.29%**有意 (採用)**
delta は閾値の 10 倍超で n=3 のまま確定 (escalation 不要)。post の σ が pre より小さい傾向 (final 1.02→0.22%) は alloc 由来の jitter が消えたことと整合。

4. per-kernel 内訳 — 効果は alloc/往復を持つ kernel に集中

timing labelpre avg_us/callpost avg_us/calldeltaS1 の対応 Tier
ts_fwd_project1,786.8739.5**-58.6%**A (out2d/depths resident 化)
ts_project_back1,908.8900.6**-52.8%**B (splats_grad buffer 直結、Vec 再 upload 撤廃)
ts_fwd_rasterize3,923.32,318.7**-40.9%**A+B (out/final_t/last_contrib resident + splats2d/sorted_idx/tile_offsets 直結)
ts_backward_raster8,939.57,104.5**-20.5%**A+B (splats_grad resident + 入力 buffer 直結)
ts_adam2,643.62,591.2-2.0%C (AdamUniforms 統合、小物)
ts_fwd_radix_sort5,239.35,144.1-1.8%— (S1 対象外、不変であることの sanity)
ts_fwd_emit_pairs499.4494.7-0.9%— (C0 で resident 済、不変)
final regime n=3 の avg_us/call。S1 が触っていない radix_sort / emit_pairs が ±2% 内で不変なのに対し、alloc + Vec 往復を持っていた 4 kernel が -20〜59% 落ちており、attribution が仮説と一致。

5. DispatchAttribution (S1 新設計測 4 点) — alloc 成分の消滅を直接証明

S1 は `{upload, alloc, gpu, readback}` の 4 成分計測 (`DispatchAttribution`、emit_pairs の C0 Day 0 計測と同型) を project_soa / raster_fwd / raster_bwd / project_back の 4 dispatch に新設した。pre 側には計測が存在しない (計測自体が S1 の一部) ため、before は per-kernel 全体値 (§4) で、after は内訳で示す。

dispatch (post、final regime)upload µs/callalloc µs/callgpu µs/callreadback µs/call
ts_project_soa5.4**0.1**520.20
ts_raster_fwd5.9**0.2**2,306.70
ts_raster_bwd5.063.2 (※)5,912.20
ts_project_back9.1**0.0**884.40
※ ts_raster_bwd_alloc の 63.2 µs は buffer alloc ではなく active 範囲 memset (`n*9*4` ≈ 14.7MB の zero clear、正しさに必須) の実測値。純粋な alloc 成分は 4 dispatch とも 0.0〜0.2 µs/call = 「resident 化で per-iter alloc が消えた」ことの直接証明。Tier C の zero_grads は `ts_zero_grads` 393.6 µs/call として新規に可視化 (pre は ts_* 計測外で不可視だった)。

6. 12.5k full gate — rep1 が PSNR guard 外 → n=3 escalation で tail variance と確定

runPSNR (mean val, 100 views)wallclockfinal splats
rep1 (lego-s1-resident-12500)36.051 dB272.36s407,556
rep236.168 dB257.55s406,321
rep336.224 dB254.73s406,304
**n=3 mean****36.148 dB****261.55s**—
PSNR guard: rep1 単発は guard 外 (-0.14)、n=3 で PASS

rep1 の 36.051 dB は歴代同 recipe 7 run の分布 (36.138〜36.226、mean 36.185) の下に外れ、±0.1 dB guard を単発では割った。S1 は数学的同値 (ForwardState buffer handle の bit-exact parity / resident buffer の byte-stability を test で証明済み、非決定性は既知の atomic 加算順序のみ) のため systematic な品質劣化の機構がなく、run 分散の tail を疑って n=3 に escalation → rep2 36.168 / rep3 36.224 dB と分布内に戻った。n=3 mean 36.148 dB = 基準 36.19 比 -0.04 dB で guard 内 PASS。歴代最低値の単発観測を機に「PSNR guard も wallclock 同様 n=1 判定は分散に飲まれうる」ことを記録する (phase5 の -0.65 dB 撤回事例、full-run wallclock 分散 ~10% と同根)。

wallclock は rep mean 261.55s で、S1 前の公式 336.33s (p2-last-contributor) 比 **-22.2%**、同 recipe 当日近傍の calib run 360.96s 比 -27.5% — replay bench の -22.9% と方向・規模とも整合する (full run は分散 ~10% があるため参考値、gate 判定は replay を正とする)。

7. msplat 等価 gap への寄与

同日等価比較 (p2-msplat-parity-lego、msplat 本日実測 167.7s) の gap は本実装 352.27s 基準で 2.10× だった。S1 後の 12.5k は rep mean 261.55s のため、同 protocol 換算で gap は 1.56× に縮小 (公式値どうしの比較 336.33s→261.55s)。Phase 2 完了時の残 bottleneck (backward 21.0% / radix 13.5% / forward rasterize 9.8%) のうち backward / forward の alloc+往復成分を刈り取った形で、次の主要残差は radix_sort (~5.1ms/iter、23%) と SSIM (~2.4ms/iter) になる。

8. 判定

  • **verdict: 採用 — flag なしの無条件変更として default 化** (S1 は挙動同値の実装改善であり A/B flag を持たない。旧経路は `binning = "per_iter_alloc"` / C3 fallback として温存され、test が両経路を検証し続ける)
  • 根拠: replay bench final -22.95% / iter5000 -21.86% (閾値の 10 倍超)。per-kernel / attribution の両面で「効果は alloc + Vec 往復を持つ kernel に限定され、対象外 kernel は不変」という仮説どおりの選択的な削減
  • PSNR guard は n=3 escalation の上で PASS (rep1 tail は上記 callout 参照)。数学的同値性は unit test (byte-stability / parity) で担保
  • 副次効果: DispatchAttribution 4 点 + ts_zero_grads の計測が per-iter コスト構造の可視化を binning 以外にも拡張 — 以後の変更は upload/alloc/gpu/readback の帰属付きで gate できる
  • 教訓: PSNR guard の n=1 判定は run 分散に飲まれうる (歴代最低値でも tail でありうる)。guard 割れ時は「機構の有無を先に監査 → n escalation」の順で判定する (wallclock の bench harness 規約と同じ思想)

9. 関連

  • 実装: `splat/crates/splat-metal/src/kernels/{project,rasterize,adam,tile_bin}.rs`、`splat/crates/splat-metal/src/param.rs`、`splat/crates/splat-train-v1/src/{trainer,train_loop}.rs`、shader: `splat/shaders/opt/adam.metal`
  • gate 用 config: `splat/configs/2026-08-16-s1-bench-*.toml` (replay 4) + `2026-08-16-lego-s1-resident-12500{,-rep2,-rep3}.toml` (full run 3)
  • replay bench raw 出力: `splat/runs/bench-s1/*.toml` (gitignore 対象、再生成可能)
  • bench harness 規約: `docs/findings/p2-bench-harness-calibration.toml`
  • C3 相互作用の詳細: `docs/findings/p2-c3-tile-counting.toml` (panic guard の設計意図)
02

関連する run

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

03

関連 finding

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