[{"data":1,"prerenderedAt":289},["ShallowReactive",2],{"finding:p3-per-splat-backward-tg256":3,"finding-runs:p3-per-splat-backward-tg256":204,"finding-related:p3-per-splat-backward-tg256":205},{"meta":4,"impact":41,"sections":47},{"id":5,"title":6,"subtitle":7,"eyebrow":8,"date":9,"status":10,"category":11,"polarity":12,"axes":13,"tags":16,"task_code":25,"commit":26,"branch":27,"config_paths":28,"related_runs":35,"related_findings":36},"p3-per-splat-backward-tg256","M3b per-splat backward 第 2 版 (256-thread threadgroup) — NO-GO 確定 (occupancy 仮説は方向的に正しいが不十分)","第 1 版 (\u003Ccode>rasterize_backwards_per_splat\u003C\u002Fcode>、32-thread\u002Fthreadgroup、bench で default 比 +34.1% regression) の finding が挙げた「低 occupancy が最有力仮説」を検証するため、\u003Cstrong>アルゴリズム・diagonal scheduling は完全に同一のまま `PER_SPLAT_BATCH` だけ 32→256 (= 16×16 tile 全体、`pso_min256` 対象) に変えた\u003C\u002Fstrong> 新 kernel \u003Ccode>rasterize_backwards_per_splat_tg256\u003C\u002Fcode> (flag \u003Ccode>backward_scheme = \"per_splat_tg256\"\u003C\u002Fcode>) を追加した。GPU 検証 (PSO compile \u002F parity 3 本 \u002F trainer 統合 parity \u002F 4-way bench) を実施した結果、\u003Cstrong>tg256 は第 1 版比 -4.22% (occupancy 仮説の方向は正しい) だが、default per_pixel 比 +32.8% で依然として大幅に遅く NO-GO 確定\u003C\u002Fstrong>。12.5k gate は実施していない (bench の時点で明確に劣後のため)。","2026-09 seminar05 milestones · M3b · per-splat backward 第 2 版","2026-08-30","stable","experiment","mixed",[14,15],1,3,[17,18,19,20,21,22,23,24],"seminar05-milestones","m3b","per-splat-backward","occupancy","threadgroup-size","diagonal-scheduling","rasterize-backward","gpu-pending","2026-09-seminar05-milestones.md — M3 追補 (per-splat backward 第 2 版、occupancy 仮説検証)","11883d2040ac","worktree-agent-a482fa3fb2a013874",[29,30,31,32,33,34],"splat\u002Fconfigs\u002F2026-08-30-m3-bench-perpixel-final.toml","splat\u002Fconfigs\u002F2026-08-30-m3-bench-perpixel-unopt-final.toml","splat\u002Fconfigs\u002F2026-08-30-m3-bench-persplat-final.toml","splat\u002Fconfigs\u002F2026-08-30-m3-parity-persplat-candidate.toml","splat\u002Fconfigs\u002F2026-08-30-m3b-bench-persplat-tg256-final.toml","splat\u002Fconfigs\u002F2026-08-30-m3b-parity-persplat-tg256-candidate.toml",[],[37,38,39,40],"p3-per-splat-backward","p2-w1-warp-sparse-skip","p2-last-contributor","p2-bench-harness-calibration",{"summary":42,"rank":43,"verdict":44,"delta_psnr":45,"delta_wallclock":46},"第 1 版 finding (`p3-per-splat-backward.toml` §5) の occupancy 仮説を検証するため、`rasterize_backwards_per_splat_tg256` (`BackwardSchemeKind::PerSplatTg256`、flag `per_splat_tg256`) を追加した。**アルゴリズム面では第 1 版と一字一句同一** (diagonal scheduling、pixel 側 state 復元、last_contributor を使わない理由、gradient 式) で、変えたのは `PER_SPLAT_BATCH` (= threadgroup thread 数) の 1 パラメータのみ (32→256)。GPU 検証: (1) `rasterize_psos_compile` PASS — `pso_min256` の 256-thread occupancy floor をレジスタ圧迫なしに達成。(2) parity 3 本 (`backward_per_splat_tg256_matches_per_pixel_original` [32×32\u002F24×24]、`_multi_round` [n=600, rounds=3]、`_byte_equality_single_pixel`) 全 PASS。(3) trainer 統合レベル `splat bench --parity` (実 checkpoint 409,660 splats) — 5 grad tensor 全て tol (atol\u002Frtol=1e-4) 内で PASS、`sorted_idx` は既知の非決定性 (0.222% 差、非 gate)。(4) 4-way bench (median ms\u002Fiter, n=3, warmup=10\u002Fiters=50\u002Frepeats=3): per_pixel (default, σ0.59%) **13.548** \u002F per_pixel unopt (σ0.34%) 15.701 \u002F per_splat v1 (σ0.12%) 18.787 \u002F **per_splat_tg256 (σ0.35%) 17.994**。tg256 は v1 比 **-4.22%** — §3 が予告した 3 効果 (barrier 総数 4.5 分の 1 \u002F thread-iteration 効率 1.78 分の 1 悪化 \u002F barrier 単価上昇) の net が僅かに改善方向に振れたことを示し、occupancy 仮説は**方向としては裏付けられた**。しかし default per_pixel 比では **+32.8%** で依然として大幅に劣後しており、M3 系列 (per-splat backward、atomic なし構造) はこの bench harness 上で **NO-GO 確定**。12.5k gate は実施していない (bench の時点で `max(2σ,1%)` の閾値を大幅に超えて劣後することが明白なため、instructions の「遅ければ gate せず終了」に従った)。`BackwardSchemeKind` の default は `PerPixel` のまま、`.rs` は無変更。","mid","no-go-confirmed","N\u002FA (bench のみ、12.5k gate 未実施。trainer 統合 parity は5 grad tensor 全て tol 内で PASS — correctness は確認済み)","tg256 vs default per_pixel: **+32.8%** (劣後、bench median 17.994ms vs 13.548ms, n=3)。tg256 vs per_splat v1: -4.22% (occupancy 仮説の方向は正しい)。12.5k gate 未実施 (bench 時点で NO-GO 確定のため)",[48,51,54,69,71,76,78,85,87,116,120,122,130,132,135,174,177,180,182],{"type":49,"text":50},"lead","本 finding は \u003Cstrong>「実装完了、GPU 検証は次段」という中間状態\u003C\u002Fstrong>を記録する。到達点がどうであれ finding を追記する規約 (`docs\u002Farchitecture\u002Fbackend-and-compiler-conventions.md`) に従い、実装の設計・第 1 版との差分・parity test の設計・そして \u003Cstrong>まだ検証していないことを検証していないと明示する\u003C\u002Fstrong>ために書く。GO\u002FNO-GO の判定は次段の GPU session に持ち越し。",{"type":52,"text":53},"heading","1. 実装 — 第 1 版とアルゴリズムは同一、PER_SPLAT_BATCH のみ 32→256",{"type":55,"items":56},"kv",[57,60,63,66],{"key":58,"value":59},"変更点は 1 パラメータだけ","第 1 版 (`rasterize_backwards_per_splat`、`PER_SPLAT_BATCH = 32`) をコピーし、`PER_SPLAT_BATCH_TG256 = 256` (= `PS_TILE_SIZE`、16×16 tile 全体) に変えただけの kernel `rasterize_backwards_per_splat_tg256` を追加した。diagonal scheduling の式 (`pixel_rank = i - lid`)、T の復元・early-out (`next_T \u003C= 1e-4` で sentinel 0.0)、gradient 式、tile ごとの atomic emit 1 回、すべて第 1 版と同一。`PER_SPLAT_BATCH_TG256 == PS_TILE_SIZE` なので pixel 初期化ループ (第 1 版は 8 pixel\u002Fthread) が 1 thread = 1 pixel の 1:1 対応に簡略化される以外、コード上の差分は定数 1 個と threadgroup dispatch サイズだけ",{"key":61,"value":62},"PSO と occupancy 規約","第 1 版は 32-thread dispatch のため `pso_min256` (256-thread occupancy floor、コンパイラ規約 C6) の対象外と判断し `pso_with_constants` (floor なし) を使っていた。本 kernel は 256-thread\u002Fthreadgroup (= tile 全体) で dispatch するため、他の全 kernel (forward\u002Fbackward per_pixel 系\u002Ftg\u002Fsimd) と同じ `pso_min256` を使う — **これが第 1 版から見た『他 kernel と同じ occupancy 規約に合わせる』という変更の核心**",{"key":64,"value":65},"Rust 側のリファクタ","`Rasterize::backward_per_splat_from_buf` (第 1 版の公開 API) と新規 `backward_per_splat_tg256_from_buf` はどちらも private helper `backward_per_splat_dispatch(pso, tg_threads, ...)` に委譲する形にした。buffer binding・grad buffer 管理・S1 attribution 記録は完全共通、PSO 参照と threadgroup thread 数 (32 or 256) だけが呼び出し元で異なる。第 1 版実装時点で存在した重複コード (90 行超のほぼ同一関数) をこのタイミングで解消した",{"key":67,"value":68},"config \u002F wiring","`BackwardSchemeKind::PerSplatTg256` (flag 値 `per_splat_tg256`) を `splat-metal::kernels::rasterize` と `splat-train-v1::config` の両方に追加 (実行時 mirror の対応関係は既存の `PerSplat` と同型)。`BackendConfig::validate` の no-op warning (`backward`\u002F`raster_backward_range`\u002F`raster_backward_sparse` が per_splat 系では無視される) を両 variant 対象に拡張。`util.rs::apply_backend_config` と `trainer.rs` の 2 dispatch call site を if\u002Felse から 3-way match に変更 (`PerPixel`\u002F`PerSplat`\u002F`PerSplatTg256`)。default は `PerPixel` のまま無変更",{"type":52,"text":70},"2. 仕様からの逸脱 — 「barrier 1-2 回\u002Fbatch」は 1 thread=1 splat + register 累積と両立しない",{"type":72,"label":73,"variant":74,"text":75},"callout","spec deviation の明示 (advisor レビュー指摘 #3)","warning","本タスクの依頼文は「batch 境界の barrier は 1 batch あたり 1-2 回に抑える」ことを目標に挙げていたが、\u003Cstrong>これは『1 thread = 1 splat + splat 側勾配を register に累積 (atomic 不要)』という制約と構造的に両立しない\u003C\u002Fstrong> — alpha compositing は pixel ごとに順序依存 (前の splat の合成結果 `pix_acc`\u002F`T` を次の splat が読む) なので、diagonal scheduling で 1 thread = 1 splat を保ったまま複数 splat の合成を並列化するには、diagonal の 1 iteration ごとに pixel 側 state の可視性を保証する `threadgroup_barrier` が必須になる (brush PR #401 自身も同じ制約を持つ)。「barrier を 1-2 回\u002Fbatch に抑える」を文字通り実現する唯一の経路は『1 thread = 1 pixel、splat を threadgroup memory に staging』という構造だが、これは (a) register 累積を失い atomic を再導入する、(b) 既に禁忌リスト入りしている `bwd-tg` staging パターン (backward への Tg staging = busy -79%、docs\u002Fstrategy\u002F2026-08-msplat-gap-sweep.md 大原則 4) と同型になる、の 2 点で不適格。\u003Cstrong>本実装は「1 thread = 1 splat + register 累積」という依頼の他の要件を優先し、barrier 回数の目標は『batch あたり 1-2 回』ではなく『barrier 総数を第 1 版比で削減する』(§3 参照) という代替目標に読み替えた\u003C\u002Fstrong>。",{"type":52,"text":77},"3. 理論的な期待効果 — ただし 3 つの効果が 1 本の実験に同居する (未検証)",{"type":79,"items":80},"list",[81,82,83,84],"**barrier 総数の削減 (期待: 改善方向)**: tile 内 splat 数 N に対し、1 round あたりの `total_iters = batch + PS_TILE_SIZE - 1`、round 数 `= ceil(N \u002F batch)` なので、tile あたりの barrier 総数の近似式は `N + (PS_TILE_SIZE - 1) * N \u002F batch`。batch=32: `N + 255N\u002F32 ≈ 8.97N`、batch=256: `N + 255N\u002F256 ≈ 1.996N` — **約 4.5 分の 1 に減る**","**thread-iteration 効率の悪化 (期待: 悪化方向、advisor レビューで判明)**: diagonal の 1 round で active thread が最大化するのは定常状態の iteration だけで、立ち上がり・立ち下がり (fill\u002Fdrain) の期間は active thread 数が `PS_TILE_SIZE` 未満になる。有効割合の近似は `PS_TILE_SIZE \u002F total_iters = 256 \u002F (batch + 255)` — batch=32: `256\u002F287 ≈ 89.2%`、batch=256: `256\u002F511 ≈ 50.1%`。**256-batch は fill\u002Fdrain のオーバーヘッド比率が上がり、1 iteration あたりの『有効』thread 割合が ~1.78 分の 1 に下がる** (256 thread のうち常に半分弱が diagonal の端で遊んでいる計算になる)","**barrier 1 回あたりのコスト増 (期待: 悪化方向、第 1 版 finding §5 caveat (c) が予告済み)**: 32-batch は 1 SIMD group (32 thread) 内の lockstep で barrier が実質 no-op に近いのに対し、256-batch は 8 SIMD group 間の実 cross-group sync になる。個々の barrier コストが増える","**net 効果は理論では決着しない**: 「barrier 総数 4.5 分の 1」「thread-iteration 効率 1.78 分の 1 に悪化」「barrier 単価上昇」の 3 効果が 1 本の実験 (tg256 vs 第 1 版) に同居しており、bench で tg256 が第 1 版より速くなっても遅くなっても、**この 1 arm だけでは『occupancy 仮説が正しい\u002F誤り』を単独に結論できない** — もし tg256 が負ければ「occupancy 仮説の反証」ではなく「この 3 効果の合成として負けた」としか言えない (第 1 版 finding が予告した caveat (c) そのもの)。切り分けたい場合は次段で『diagonal を batch 境界を跨いで連続させる』variant (thread lid が splat lid, lid+256, lid+512, ... を継続担当し、round 復元のたびに diagonal をリスタートしない) が必要— 同じ 256-thread occupancy を保ちつつ効率を ~80% 程度まで戻せる見込みだが、本 session のスコープ外として次段に委ねる",{"type":52,"text":86},"4. 正しさの検証状況 — 全 test GPU 実行済み、全 PASS",{"type":88,"columns":89,"align":93,"rows":95},"table",[90,91,92],"test","何を pin するか","GPU 実行状況",[94,94,94],"left",[96,100,104,108,112],[97,98,99],"`rasterize_psos_compile`","全 PSO 構築 (`rasterize_backwards_per_splat_tg256` 含む)。`pso_min256` は `maxTotalThreadsPerThreadgroup \u003C 256` で `Err` を返すため、レジスタ圧迫で 256-thread floor を割り込んでいないかもここで判明する","**PASS** — floor 達成、`Err` なし",[101,102,103],"`backward_per_splat_tg256_matches_per_pixel_original`","第 1 版と同一 fixture (32×32 \u002F 24×24、24 splat)。`abs_tol\u002Frel_tol = 1e-4` dual-threshold","**PASS** (32×32: max_abs=4.272e-4\u002Fmax_rel=1.968e-5、24×24: max_abs=1.831e-4\u002Fmax_rel=3.925e-6、dual-threshold で pass)",[105,106,107],"`backward_per_splat_tg256_matches_per_pixel_original_multi_round`","n_splats=600 (tile あたり 600 splat、`rounds = ceil(600\u002F256) = 3`) で round 境界の `pix_T`\u002F`pix_acc` 持ち越し + per-round gradient flush を確認。**advisor レビューで指摘された懸念が残る**: この fixture は `color_a = 0.88` で T が最初の数十 splat で `1e-4` sentinel に落ちるため、round 2\u002F3 では『生きた』pix_T\u002Fpix_acc の持ち越しではなく『すでに死んだ pixel への no-op』を通るだけの可能性が高い — round 境界の re-init バグ (最も起きやすい種類のバグ) は検出できるが、doc comment が主張する『round を跨ぐ生きた状態遷移』の直接証明にはなっていない","**PASS** (max_abs=5.150e-5、max_rel=5.783e-2 — abs 側で dual-threshold pass。上記の fixture 限界の懸念はこの実測では解消されていない、次段への申し送り事項として残す)",[109,110,111],"`backward_per_splat_tg256_byte_equality_single_pixel`","単一 pixel 非ゼロ dldr で Original+FullRange+Off と bit 一致 (第 1 版と同型)","**PASS**",[113,114,115],"`splat bench --parity` (実 checkpoint 409,660 splats)","第 1 版と同じ 5 grad tensor (means\u002Flog_scales\u002Frot_quats\u002Fraw_opacities\u002Fsh_coeffs) の abs\u002Frel 1e-4 比較。**これが multi-round path の本命の検証** — Lego の実 tile は密な tile で 256 splat を超えるため、上記 unit fixture より遥かに現実的な multi-round 実行を踏む","**PASS OVERALL** — 5 grad tensor 全て tol 内 (means max_abs_diff=1.014e-5 が最大)、loss_value diff=3.539e-8、`sorted_idx` は非 gate の既知 tie-order 非決定性 (0.222%)",{"type":72,"label":117,"variant":118,"text":119},"GPU 実行を止めた理由 (第 1 版 session 中の coordinator 指示、参考として保持)","info","実装完了後、GPU 検証の直前に coordinator から「現在 12.5k gate (M2 Tier1 A1-A4) が直列で走っており、run の合間の短い隙間に bench を差し込むと gate を汚染する。以後 GPU を使う実行は行わず、実装と CPU 側 test・ビルドのみ進めよ」という指示を受け、実装 session はここで止めた。**本 finding の §4\u002F§5b は後続の別 GPU 検証 session (2026-08-30、A7 gate 完了後の GPU 空き窓) での実測を追記したもの** — GPU 権は main から明示的に付与され、series 直列化 (A7 gate → M3b 検証) を確認した上で実行した。",{"type":52,"text":121},"5. 次段で実行すべき GPU コマンド一覧 (優先順、§5b に実測結果)",{"type":79,"items":123},[124,125,126,127,128,129],"**(1) 最優先・最も情報量が高い**: `cargo test --release -p splat-metal rasterize_psos_compile` — 数秒の GPU 使用で `pso_min256` が `rasterize_backwards_per_splat_tg256` の `maxTotalThreadsPerThreadgroup >= 256` を満たすか判定する。**もしここで `Err` (occupancy floor 未達) になった場合、それ自体が M3b の結論になる** (『256-thread dispatch はレジスタ圧迫でこの kernel には実現不能』) — `pso_with_constants` に差し替えて floor を回避することは可能だが、その場合 256 thread を実際に dispatch できず本実験の前提が崩れるため、値をそのまま記録し次の判断を main に仰ぐこと","**(2) parity (unit level)**: `cargo test --release -p splat-metal backward_per_splat_tg256` (3 test: matches_per_pixel_original \u002F matches_per_pixel_original_multi_round \u002F byte_equality_single_pixel)","**(3) parity (trainer 統合レベル)**: `cargo build --release` 後、`.\u002Ftarget\u002Frelease\u002Fsplat bench --config configs\u002F2026-08-30-m3-bench-perpixel-final.toml --parity configs\u002F2026-08-30-m3b-parity-persplat-tg256-candidate.toml` (第 1 版と同じ baseline config、candidate だけ tg256 に差し替え)","**(4) 4-way bench replay** (各 arm \u003C 2 分、4 arm 合計でも 10 分未満の見込み): `.\u002Ftarget\u002Frelease\u002Fsplat bench --config configs\u002F2026-08-30-m3-bench-perpixel-final.toml` (default) \u002F `configs\u002F2026-08-30-m3-bench-perpixel-unopt-final.toml` (unopt) \u002F `configs\u002F2026-08-30-m3-bench-persplat-final.toml` (第 1 版) \u002F `configs\u002F2026-08-30-m3b-bench-persplat-tg256-final.toml` (第 2 版、新規)。判定は `docs\u002Ffindings\u002Fp2-bench-harness-calibration.toml` の規約 `max(2σ, 1%)` — tg256 が default per_pixel を有意に下回れば GO 方向、そうでなければ NO-GO","**(5) GO の場合のみ**: gate 用 config `2026-08-30-m3b-12500-{perpixel,tg256}-r{1,2,3}.toml` (base: `configs\u002F2026-08-30-t1-12500-on-r1.toml`、依頼文の指定どおり) を作成し、main に gate 発注を仰ぐ","**事前準備 (完了済み)**: `runs\u002Flego-bench-calib-checkpoints\u002Ffinal.ply` を main repo (`\u002FUsers\u002Fotkrickey\u002Fdev\u002Fmatsudalab\u002Fsplat\u002Fruns\u002F...`) からこの worktree の同パスにコピー済み (`runs\u002F` は gitignore 対象で worktree ごとに空だったため、bench config の相対パスがそのままでは解決しなかった — advisor レビュー指摘)。`runs\u002Fbench-m3` \u002F `runs\u002Fbench-m3b` ディレクトリも作成済み",{"type":52,"text":131},"5b. 実測結果 (2026-08-30 GPU 検証 session、main HEAD 3fc6dea 上)",{"type":72,"label":133,"variant":118,"text":134},"binary provenance — A7 default flip 前の binary で計測","本 §5b の全計測 (PSO compile \u002F parity 3 本 \u002F trainer統合 parity \u002F 4-way bench) は binary sha256 `23bf1d73dbc000515fcf09b480998f829afd5f473e99472a9777db0858b4abb7` (git rev `3fc6dea`、`refine_scratch_persist`\u002F`refine_direct_write` の default は **まだ false**) で実行した。同一セッション後半で A7 gate 採用に伴い上記 2 flag の default を true に flip している (`p3-refine-3pass.toml` 参照) が、`splat bench` は `train_step` を直接叩く replay harness で refine tick (100 iter に 1 回) を経由しないため、この flip は本 §5b の数値に影響しない。ただし 4-way bench の 4 config (`2026-08-30-m3*-bench-*-final.toml`) はいずれも refine flag を明示しておらず、flip 後に再実行すると effective config が変わる点は再現時の注意事項として明記する。",{"type":88,"columns":136,"align":143,"rows":145},[137,138,139,140,141,142],"config","backward_scheme","median ms\u002Fiter (n=3)","σ (%)","vs default per_pixel","GPU busy%",[94,94,144,144,144,144],"right",[146,153,160,167],[147,148,149,150,151,152],"2026-08-30-m3-bench-perpixel-final (default)","PerPixel","13.548","0.59%","—","79.3%",[154,155,156,157,158,159],"2026-08-30-m3-bench-perpixel-unopt-final","PerPixel (unopt: Original\u002FFullRange\u002FOff)","15.701","0.34%","+15.9%","82.0%",[161,162,163,164,165,166],"2026-08-30-m3-bench-persplat-final (第 1 版)","PerSplat","18.787","0.12%","+38.7%","85.0%",[168,169,170,171,172,173],"2026-08-30-m3b-bench-persplat-tg256-final (第 2 版)","PerSplatTg256","17.994","0.35%","**+32.8%**","84.3%",{"type":72,"label":175,"variant":74,"text":176},"判定 — NO-GO 確定。occupancy 仮説は方向として裏付けられたが不十分","tg256 (17.994ms) は第 1 版 (18.787ms) より **-4.22%** 速く、§3 が挙げた 3 効果 (barrier 総数 4.5 分の 1 に改善 \u002F thread-iteration 効率 1.78 分の 1 に悪化 \u002F barrier 単価上昇) の net が僅かに改善方向に振れたことを示す — \u003Cstrong>occupancy 仮説そのものは方向として裏付けられた\u003C\u002Fstrong>。しかし default per_pixel (13.548ms) と比べると tg256 は依然として \u003Cstrong>+32.8%\u003C\u002Fstrong> 遅く、`max(2σ,1%)` のどんな緩い閾値でも埋まらない差である。per-splat backward (atomic なし構造、brush PR #401 型) は 32-thread 版・256-thread 版のいずれの構成でも本実装の per_pixel (SIMD warp-level 最適化済み、atomic 使用) に対して優位性を示せなかった — \u003Cstrong>M3 系列 (per-splat backward) はこの bench harness 上で NO-GO 確定\u003C\u002Fstrong>とする。12.5k gate は実施していない (bench 時点で閾値を大幅に超えて劣後することが明白なため)。`BackwardSchemeKind` の default は `PerPixel` のまま、`.rs` は無変更。",{"type":72,"label":178,"variant":118,"text":179},"次に狙うなら — diagonal を batch 境界を跨いで連続させる variant (未着手)","§3 が示唆した『diagonal を batch 境界を跨いで連続させる』variant (thread lid が splat lid, lid+256, lid+512, ... を継続担当し、round 復元のたびに diagonal をリスタートしない) は同じ 256-thread occupancy を保ちつつ thread-iteration 効率を ~80% 程度まで戻せる見込みだったが、+32.8% のギャップを埋めるには焼け石に水の可能性が高い (効率改善だけで barrier 単価増・atomic なし化のオーバーヘッドを覆すには不十分と見られる)。M3 系列への追加投資は費用対効果が低いと判断し、本 finding をもって M3 系列の探索は打ち切りとする。",{"type":52,"text":181},"6. ファイル一覧 (このセッションの変更)",{"type":55,"items":183},[184,187,190,192,195,198,201],{"key":185,"value":186},"kernel","`splat\u002Fshaders\u002Fbackward\u002Frasterize_backwards.metal` — `rasterize_backwards_per_splat_tg256` を追加 (第 1 版・既存 3 kernel は無変更)",{"key":188,"value":189},"Rust dispatch","`splat\u002Fcrates\u002Fsplat-metal\u002Fsrc\u002Fkernels\u002Frasterize.rs` — `BackwardSchemeKind::PerSplatTg256`、`pso_backward_per_splat_tg256`、共通 helper `backward_per_splat_dispatch` へのリファクタ、`backward_per_splat_tg256_from_buf`、parity test 3 本 (matches\u002Fmulti_round\u002Fbyte_equality)",{"key":137,"value":191},"`splat\u002Fcrates\u002Fsplat-train-v1\u002Fsrc\u002Fconfig.rs` — `BackwardSchemeKind::PerSplatTg256` (flag `per_splat_tg256`)、`validate()` の no-op warning 拡張",{"key":193,"value":194},"wiring","`splat\u002Fcrates\u002Fsplat-cli\u002Fsrc\u002Futil.rs::apply_backend_config`、`splat\u002Fcrates\u002Fsplat-train-v1\u002Fsrc\u002Ftrainer.rs` (2 dispatch call site を 3-way match に変更)",{"key":196,"value":197},"bench config (新規)","`splat\u002Fconfigs\u002F2026-08-30-m3b-bench-persplat-tg256-final.toml`、`splat\u002Fconfigs\u002F2026-08-30-m3b-parity-persplat-tg256-candidate.toml`",{"key":199,"value":200},"gate config","未作成 (§5 の (5) 参照、bench が GO の場合のみ作成する方針)",{"key":202,"value":203},"commit","`1c12660` (kernel + wiring)、`11883d2` (multi-round test 追加) — worktree `worktree-agent-a482fa3fb2a013874`。本 finding は次 commit",[],[206,225,246,268],{"id":37,"title":207,"date":9,"status":10,"polarity":12,"category":11,"axes":208,"tags":209,"task_code":217,"related_runs":218,"delta_psnr":219,"delta_wallclock":220,"rank":221,"verdict":222,"impact_summary":223,"detail_path":224},"M3 per-splat backward (brush PR #401 型) — 正しさ PASS (full-scale parity) だが wallclock +34.1% regression",[14,15],[17,210,19,211,22,23,212,213,214,215,216],"m3","brush-pr-401","atomic-float","parity","backend-config","regression","lego","2026-09-seminar05-milestones.md — M3 per-splat backward (brush PR #401 型)",[],"N\u002FA (bench replay は 1 checkpoint に対する forward+backward+adam の反復であり学習軌道ではない。12.5k trainer gate は regression 判明のため未実施)","**bench replay 3-way (Lego final checkpoint 409,660 splats、800×800、iters=50×repeats=3、pipelining=off 固定)**: per_pixel(default: simd+warp_any+lc) **15.354** ms\u002Fiter → per_pixel(unopt: original+full_range+off) **17.681** ms\u002Fiter → per_splat **20.594** ms\u002Fiter。**per_splat vs default = +34.1%、per_splat vs unopt = +16.5%**。GPU busy ms\u002Fiter: 12.499 → 14.914 → 17.753 (per_splat が unopt 比でも +19.0%)。sync-tax ms\u002Fiter は 3 arm とも 2.79〜2.87 でほぼ不変。σ: default 1.08% \u002F unopt 0.31% \u002F per_splat 0.17% (n=3、いずれも安定)。**per_splat 自身の self-noise: max_rel 5.1e-6 (32×32 unit fixture) \u002F 0 (24×24、bit-exact) — atomic 版 Original の self-noise 4.5e-5 の 1\u002F9 以下**","high","m3-per-splat-backward-correct-but-slower-not-recommended-for-default","M3 の実装フェーズ (spec: docs\u002Fstrategy\u002F2026-09-seminar05-milestones.md) を完了した。**新 kernel `rasterize_backwards_per_splat` を既存 3 kernel (Original\u002FSimd\u002FTg) と並存する別 entry として追加**し、`BackendConfig.backward_scheme` (`per_pixel` default \u002F `per_splat`) で配線した。**正しさの証拠は 2 層で強い**: (1) unit-level — 単一 pixel fixture で `Original`(FullRange,Off) と bit 一致、multi-pixel fixture (32×32\u002F24×24) で `abs\u002Frel 1e-4` dual-threshold PASS (milestone spec の 1e-5 は `Original` 自身の run-to-run self-noise 4.54e-5 より厳しく、達成不能と判明したため 1e-4 に補正)。(2) **trainer 統合レベル** — `splat bench --parity` で実 checkpoint (Lego final、409,660 splats、sh_degree=3) の 1 iteration を実行し、`means\u002Flog_scales\u002Frot_quats\u002Fraw_opacities\u002Fsh_coeffs` の全 grad tensor が **既存 backward variant (Original vs Simd\u002FTg) と同じ `abs=1e-4 rtol=1e-4` tolerance で PASS** (max_abs_diff は 5.8e-8 〜 2.8e-5 の範囲、既存 Tg の文書化済み値 2.811e-5 と同オーダー)。**性能は逆方向の結果、しかも「比較が不公平」では説明できない** — bench replay を **3-way** で取った: per_splat (20.594 ms\u002Fiter) は現行 default (per_pixel = Simd+WarpAny+LastContributor、15.354 ms\u002Fiter) 比 **+34.1%** 遅いだけでなく、**W1a\u002FLastContributor 等の最適化を一切持たない per_pixel (Original+FullRange+Off、17.681 ms\u002Fiter) 比でも +16.5% 遅い**。GPU busy ms\u002Fiter は per_splat 17.753 に対し per_pixel(unopt) 14.914 で、sync-tax はどの arm も ~2.8〜2.9ms\u002Fiter で揃っている — つまり待ち時間の付け替えではなく **transposed loop nest 構造そのものが Apple GPU 上で不利**という決定的な結果になった。brush が報告する backward -25% とは逆方向。**副次効果 (atomic 順序依存の消失) は実証できた** — per_splat 自身の self-noise は max_rel 5.1e-6 (32×32) \u002F 完全 bit-exact (24×24) で、atomic 版 `Original` の self-noise (4.5e-5) の 1\u002F9 以下。**この regression で 12.5k trainer 統合 gate (wallclock Δ \u002F PSNR guard) を見送る判断をした** — gate 用 config 6 本は作成済み (`splat check` で deserialize 確認済み) だが、bench 3-way の時点で明確な regression が出ているため、main が別途 12.5k で確認を望む場合のみ実行すればよい状態で残す。`cargo build --release` + `cargo test --release` (全 workspace 80+70+8 test) は全 pass、per_pixel default (既存挙動) は無変更。","\u002Ffindings\u002Fp3-per-splat-backward\u002F",{"id":40,"title":226,"date":227,"status":10,"polarity":228,"category":229,"axes":230,"tags":231,"task_code":239,"related_runs":240,"delta_psnr":-1,"delta_wallclock":242,"rank":221,"verdict":243,"impact_summary":244,"detail_path":245},"splat bench harness 実装 + calibration — σ_replay 0.83%、full run 比 ~6x ノイズ削減","2026-08-16","positive","tooling",[14,15],[232,233,234,235,236,237,238,216],"bench-harness","calibration","variance","reproducibility","c7","fixed-workload","gate-infra","splat bench harness (2026-08-16 GPU 専有タスク)",[241],"lego-bench-calib-checkpoints","σ_replay 0.83% (n=10, final-scale workload) vs full run 実測 ~10% — 約 6x ノイズ削減","accepted","`splat bench --config bench.toml` を実装し、同一 config n=10 replay で \u003Cstrong>σ_replay = 0.234 ms\u002Fiter (mean 28.339 ms 比 0.83%)\u003C\u002Fstrong> を実測。full training run で観測されていた ~10% 分散に対し \u003Cstrong>約 6x のノイズ削減\u003C\u002Fstrong>。3-regime (iter 1000 \u002F 5000 \u002F final checkpoint、各 n=5) でも σ 1.2-4.6% の範囲に収まり、splat 数が少ない早期 regime ほど相対分散が大きい傾向を確認。有意判定閾値を \u003Ccode>max(2σ, 1%)\u003C\u002Fcode> と規約化し、以後の gate 判定をこの harness の計測に載せ替える。付随して `--parity` (kernel variant 間の勾配 \u002F binning 一致検証) と `[output] save_ply_at` (checkpoint 保存) を実装、parity mode の実測で production-scale シーンの `sorted_idx` tie-order 非決定性 (~0.2%、真の非決定性であって variant 差ではない) を発見し gate から除外した。","\u002Ffindings\u002Fp2-bench-harness-calibration\u002F",{"id":39,"title":247,"date":227,"status":10,"polarity":228,"category":11,"axes":248,"tags":249,"task_code":257,"related_runs":258,"delta_psnr":263,"delta_wallclock":264,"rank":221,"verdict":265,"impact_summary":266,"detail_path":267},"P2 gap sweep Phase 2 — 2-BWD last_contributor で -15.0% (数学的同値)、STP 再判定は棄却",[14],[250,251,252,253,254,255,256,216],"gap-sweep","phase-2","2-bwd-last-contributor","backward","stop-the-pop","re-eval","function-constant","2026-08 msplat gap sweep Phase 2 2-BWD \u002F STP 再判定",[259,260,261,262],"lego-lc-smoke-1k","lego-p2lc-12500","lego-stp-c0-12500","lego-stack-lc-stp-12500","LC 12.5k gate: 36.183 → 36.191 dB = +0.008 dB (数学的同値実装、atomic 非決定性 guard ±0.1 内)","LC 12.5k gate: 395.59 → 336.33s = **-14.98%** (backward_raster -40.3%)。STP: -2.51% (gate 未達)、LC+STP スタック: 343.63s (LC 単独より +2.2%)","lc-adopted-minus-15-percent-stp-rejected-final","C0 (-48.4%) に続く Phase 2 第 2 弾で、backward 31.4% の新 bottleneck を kernel 側から -40.3% 削減。\u003Cstrong>Lego 12.5k = 336.33s で msplat 30K (220s) 比 1.53× まで縮小\u003C\u002Fstrong>し、gap sweep の目標 (≤2.0×) を達成した。実装は「forward が既に知っている打ち切り位置を backward に伝えるだけ」で数学的同値 — 品質を 1 bit も動かさずに backward の replay 計算量を ~40% 削った。STP 再判定は負の結果だが価値が高い: Phase 1a の -7.45% の正体が C0 と同じ page fault 削減だったことを分離実証し、「効果の重複を疑って再 bench する」protocol の正しさを裏付けた。次の bottleneck は forward rasterize 9.8% \u002F radix 13.5% \u002F SSIM 7.5% でいずれも trigger 25% 未達 — Phase 2 はここで完了、Phase 3 (再計測 + Pareto v3) へ。","\u002Ffindings\u002Fp2-last-contributor\u002F",{"id":38,"title":269,"date":227,"status":10,"polarity":228,"category":11,"axes":270,"tags":271,"task_code":279,"related_runs":280,"delta_psnr":284,"delta_wallclock":285,"rank":221,"verdict":286,"impact_summary":287,"detail_path":288},"W1 warp sparse skip + exp-skip — backward -35% \u002F replay -11.2% (bit-exact)",[14],[272,273,274,275,253,276,277,256,278,216],"1x-roadmap-v2","w1","warp-sparse-skip","exp-skip","forward","simd-any","bit-exact","2026-08 1× 工程表 v2 W1",[281,282,283],"lego-w1-warpany-12500","lego-w1-warpany-12500-rep2","lego-w1-warpany-12500-rep3","12.5k gate n=3: 36.209 \u002F 36.201 \u002F 36.193 dB → mean 36.201 dB = 基準 36.148 (S1 n=3 mean) 比 +0.053 dB (guard ±0.1 内、n=3 mean 判定 — S1 の教訓に従い n=1 判定なし)","replay bench final regime: 21.724 → 19.300 ms\u002Fiter = **-11.16%** (閾値 max(2σ,1%)=2.7%)。iter5000 regime: 19.984 → 17.759 = **-11.13%** (閾値 3.1%)。backward_raster: 7.183 → 4.652 ms\u002Fcall (**-35.2%**、GPU 部 5.963 → 3.437 = -42.4%)。12.5k full run n=3: 239.74 \u002F 246.93 \u002F 237.57s → mean **241.41s** (S1 基準 261.55s 比 **-7.7%**)","w1-adopted-default-flip-warp-any","1× 工程表 v2 の第 1 波。msplat \u002F Inria \u002F brush の 3 実装が持ち本実装だけ欠落していた backward の 2 つの skip を、bit-exact の等価性論証つきで移植した。backward_raster は LC (2-BWD) 後の 7.2ms\u002Fcall から 4.65ms\u002Fcall へ -35.2% (kernel share 13.1% に低下)、replay 全体で -11.2%。12.5k full run は 261.55 → 241.41s で msplat 同日等価 gap は 1.56× → 1.44× に縮小。数学的同値の施策のみの累計は 766.07 → 241.41s = -68.5% になった。次の律速は forward (23.6%) \u002F radix (15.0%) で、W2 (encoder\u002FCB 統合) と計測 (counter session) が次段。","\u002Ffindings\u002Fp2-w1-warp-sparse-skip\u002F",1790227327656]