per-iter で 25+ 件の cmd.commit() があり、Apple Silicon GPU の schedule overhead (~0.3-0.7ms × N) が iter 全体の 20-50% を占める可能性。simpler batching (forward chain と backward chain をそれぞれ 1 cmd buffer に集約) を Option<&CommandBuffer> opt-in 形式で実装する計画。
status: plan 起草 (2026-05-23)、実装 subagent 投入予定 (A.6 完了後)。user 判断: A.7 は「scope を縮小して simpler batching として実装」 (full ICB は thesis-scope 外)。
splat-train-v1/src/train_loop.rs の per-iter で、projector.project_soa, binner.emit_pairs, binner.radix_sort, binner.extract_offsets, rasterize.forward, loss.compute_l1_combine_ssim (or l1_only), rasterize.backward, project_backwards, adam.step が すべて個別に new_command_buffer() + commit + wait_until_completed している:
grep -rn "new_command_buffer\|cmd.commit" splat/crates/splat-metal/src/kernels/
で 25+ 件の cmd.commit() が確認できる (project: 3, tile_bin: 5, rasterize: 2, ssim: 2 x 2、loss: 多数、adam: 1)。
各 commit に Apple Silicon GPU の schedule overhead (~0.3-0.7 ms M4 Max 実測) が乗るため、iter ~25 ms のうち overhead 寄与は 5-12 ms (20-50%) が見込まれる。これを集約すれば +15-30% wallclock 改善の余地。
やる:
やらない:
各 kernel method に「encode-only variant」を追加する。3 つのスタイルがあり:
impl Projector {
pub fn project_soa(&self, param: &Param, cam: &Camera) -> GpuProjectResult {
self.project_soa_in_cmd(param, cam, None) // 旧 path
}
pub fn project_soa_in_cmd(
&self,
param: &Param,
cam: &Camera,
cmd: Option<&CommandBufferRef>, // None なら内部で作って commit
) -> GpuProjectResult {
// cmd.is_none() → 旧 behavior
// cmd.is_some() → encode のみ、commit は呼び出し側
}
}
利点: 既存の test / call site は変更不要、新 path は opt-in。欠点: API surface が増える。
pub enum DispatchMode<'a> { Sync, Pipelined(&'a CommandBufferRef) }
forward() などに mode: DispatchMode を渡す。Sync で旧 path、Pipelined(cmd) で encode のみ。利点: 引数 1 個、call site は明示的に意図を書ける。欠点: 既存 call site に追加が必要。
A 推奨。理由: 既存テスト 23 件 (cargo test -p splat-metal --lib) を一切 touch せずに済む。
| kernel | 現状 commit/iter | encode-only API 必要 |
|---|---|---|
| project::project_soa | 1 | yes (forward chain) |
| project::project_soa_buf | 1 | (将来 stretch) |
| tile_bin::emit_pairs | 1 | yes |
| tile_bin::radix_sort | 1 (× ~5 passes) | yes |
| tile_bin::extract_offsets | 1 | yes |
| rasterize::forward | 1 | yes |
| rasterize::backward | 1 | yes (backward chain) |
| project::project_backwards | 1 | yes |
| ssim::forward_and_grad_buf | 2 | (将来 stretch、L1Ssim 系で) |
| loss::compute_l1_combine_ssim | 多数 | (将来 stretch) |
| adam::step | 1 | no (1 commit のみ) |
forward chain は 4-5 commit / iter → 1 commit に集約見込み。
forward_batched_matches_unbatched): 同 input で旧 path と新 path を実行、結果が bit-identical か近似一致A.4 完了後の GPU 空き時間で:
end_encoding() を忘れると Metal が panic、慎重にwait_until_completed() を呼ぶタイミング: encode-only path では呼ばない、最後の commit で呼ぶ第 3 軸 (Apple Silicon 固有最適化) の追加 row。M-3.x baseline 23m40s → ICB ICB X m Y s と書ければ評価表が 1 行充実。
正の効果なら第 3 軸論を補強 (commit overhead は Apple Silicon の特徴)。負の効果なら「commit overhead は M4 Max では既に十分小さく、batching 効果は marginal」という finding として記録 (A.10 と同レベルの honest negative finding)。
a-10-kahan-negative.mdfinal-ablation-table.mdSPLAT_F16_FORWARD=1 切替): bench は A.4 完了後この finding が観測された / 言及している実験 run。