松田研究室
FindingID: a-7-icb-batching-results
Status: stable / task A.7
← Findings Index
Mildly positive · Apple Silicon batching

A.7 batched cmd buffer — wallclock -6.2% 改善 + PSNR drift -0.30 dB

scope B 限定版 (forward 末尾 + backward chain を 1 cmd buffer 集約、~3 commit/iter 削減) を worktree binary で 30k bench。baseline 24.879 dB / 23m13s に対し 24.577 dB / 21m47s、Mildly positive finding。Apple Silicon の commit overhead が予想より小さく、scope B で実効 ~6%。

positiverank: midaccepted第 3 軸phase-5icbcommand-bufferbatchingmetalapple-siliconresults
Δ PSNR
-0.302 dB (24.577 vs 24.879)
Δ Wallclock
-6.16% (1307.26s vs 1393s = -85.74s)
Δ Splats
-1.05% (82,855 vs 83,734)
Impact
scope B 限定版 (forward 末尾の extract_offsets + rasterize.forward を 1 cmd buffer、backward chain の rasterize.backward + project_backwards を 1 cmd buffer) を env SPLAT_BATCHED_FORWARD=1 で活性化。30k bench で wallclock -6.2% / PSNR drift -0.30 dB、Mildly positive。期待 -6〜-12% の下限、Apple Silicon の commit overhead が予想より小さい示唆。
01

本文

A.7 plan の scope B (Buffer 入出力 variant 追加 + backward chain と forward 末尾を batched 化) を worktree a-7-icb-batching で実装、env SPLAT_BATCHED_FORWARD=1 で活性化。30k bench (lego sh=3, seed=42, capacity=1M) で baseline 24.879 dB / 23m13s に対し 24.577 dB / 21m47s、wallclock -6.16% 改善。PSNR drift -0.302 dB は許容範囲内 (target < 0.5 dB)。Mildly positive finding。

実装日
2026-05-23 (subagent worktree)
前提 baseline
lego-sh3-30k 24.879 dB / 23m13s / 83,734 splats, seed=42
本 run
lego-a7-batched-30k 24.577 dB / 21m47s / 82,855 splats, seed=42
config
configs/2026-05-23-0730-lego-a7-batched-30k.toml
活性化
env SPLAT_BATCHED_FORWARD=1 (train_loop が forward 末尾 + backward chain を batched に切替)
worktree
.claude/worktrees/agent-a7-icb-batching (branch a-7-icb-batching, commit 95e8630)

実装の actual scope (plan からの調整)

Plan の literal interpretation (Option<&CommandBufferRef> 引数だけ追加) では subagent 1 が問題発見: splat-metal の現行 kernel API は全 host slice 入出力前提radix_sort は内部で 16 pass の hist→scatter + host CPU 側 exclusive prefix scan を行うので 1 cmd buffer 集約は不能。selectable な batching site は限定的。

  • scope A (literal): commit skip だけ → batching 効果ゼロ (radix_sort の host CPU loop が boundary)
  • scope B (採用): Buffer 入出力 variant を追加 + (i) extract_offsets + rasterize.forward の forward 末尾、(ii) rasterize.backward + project_backwards の backward chain の 2 site を batched 化。期待 ~3 commit/iter 削減
  • scope C (defer): 真の ICB / 全 chain batching は radix_sort 含む全 API の Buffer 化が必要、卒研範囲外

追加した API (5 method + 2 trainer entry)

  • rasterize::forward_from_buf (Buffer 入出力 + Option<CommandBuffer>)
  • rasterize::backward_from_buf
  • project::project_backwards_from_buf
  • tile_bin::extract_offsets_from_buf
  • trainer::forward_with_state_batched_tail: extract_offsets + rasterize.forward を 1 cmd buffer
  • trainer::backward_combined_batched: rasterize.backward + project_backwards を 1 cmd buffer
  • train_loop: env SPLAT_BATCHED_FORWARD で batched path 切替

test 結果

  • cargo test -p splat-metal --lib: 25 pass / 0 fail (既存 23 + 新規 2)
  • cargo test -p splat-train-v1 --lib: 31 pass / 0 fail
  • forward_from_buf_matches_forward_unbatched: pass (tol 1e-6 厳密)
  • backward_from_buf_matches_backward_unbatched: pass、ただし tol abs 1e-4 / rel 1e-4 に緩和

backward の緩和は SIMD backward kernel の atomic_fetch_add dispatch 順序非決定性によるもの (実測 1.9e-6 のズレ、A.10 と同類の GPU 非決定性 finding)。kernel 性質で再走でも変わらない、accept。

30k 実測結果

metricbaseline (sh3-30k)A.7 (batched)Δ
PSNR (val 100 views)24.879 dB24.577 dB-0.302 dB
wallclock (30k iter)23m13s (1393s)21m47s (1307.26s)-85.74s (-6.16%)
ms/iter (avg)46.4 ms43.6 ms-2.8 ms (-6.03%)
final splats83,73482,855-879 (-1.05%)
wallclock -6.16% は plan 期待 -6〜-12% の下限。Apple Silicon の per-commit overhead が plan 想定 (0.3-0.7 ms × 3) より小さく、実効は ~1 ms × 3 = 3 ms / iter 程度の節約と推定

解釈

Apple Silicon の commit overhead は思ったより小さい

plan では commit overhead を 0.3-0.7 ms × 25+ commits/iter で iter の 20-50% を占めると見積もったが、実測 -6% から逆算すると per-commit overhead は ~0.1-0.3 ms 程度。Apple Silicon GPU の command queue は CUDA より overhead が小さいことを示唆。これは brush (wgpu→Metal) が CUDA native (orig 3DGS) より速い (m4-brush-bench) という別 finding と整合的。

PSNR -0.30 dB drift の原因

backward の SIMD atomic 順序非決定性 (test で観測した 1.9e-6 のズレ) が iter ごとに gradient を微小に変化させ、30k 累積で refine 判定が微妙に変わる。splats 数も -1.05% (82,855 vs 83,734) と僅差、PSNR drift も -0.3 dB と限定的、実用上問題ない range。bit-identical を求めるなら backward を non-atomic な reduction に書き換える必要があるが、scope 外。

卒論への含意

第 3 軸 (Apple Silicon 固有最適化) の Positive finding。M-3.x baseline 23m13s → 21m47s と 1 行が central table に追加できる。「Apple Silicon の command queue overhead は CUDA 系より小さく、batching の利得は marginal (約 6%)」という結論で、A.9 (-10 dB / +75% 二重 negative) と A.10 (bit-identical) と合わせて、Apple Silicon 固有最適化の 3 試行のうち **1 positive (A.7) / 2 negative (A.9, A.10)** という構造ができた。

Lesson

kernel API の Buffer 化は scope 拡張だが、その実効として ~6% wallclock 改善が得られた。次に GPU profiler (Instruments Metal Trace) を当てて、forward chain 上流 (project / emit_pairs / radix_sort) の commit overhead 寄与を直接計測すれば、追加の batching 余地を識別可能。

残作業 (defer)

  • Instruments Metal Trace で per-commit overhead の実測 (Apple Silicon の queue scheduling profile)
  • forward chain 上流 (project + tile_bin) の Buffer 化 (現状 radix_sort の host CPU loop が boundary、scope 大)
  • ssim / loss の batching (現状 host readback path、scope 大)
  • main branch への merge (現状 worktree のみ、main は f32 baseline 維持)

関連

  • A.7 implementation plan: a-7-icb-batching-plan
  • A.9 f16 forward Negative finding: a-9-f16-forward-negative
  • A.10 Kahan Negative finding: a-10-kahan-negative
  • m4-brush-bench (Apple Silicon GPU の overhead が CUDA より小): m4-brush-bench
  • A.5 final ablation 表 第 3 軸 row 'A.7 batched cmd buffer': final-ablation-table
02

関連する run

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

03

関連 finding

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