卒研中に得た実測ノートの一覧。polarity (P / N / mixed)、貢献軸 (第 1/2/3)、impact (Δ PSNR / Δ wallclock) で絞り込み + 並べ替え。
同日・同機・直列・load 記録付きで Lego 30k を brush / 本実装 1 本ずつ実行。学習時間は本実装 392.39s vs brush 417s (trainer 内部値、0.941×)、process wallclock では 395.07s vs 433.23s (0.912×)。PSNR は評価器依存が大きい: brush PLY を brush 評価器で測ると 37.41 dB、splat eval q8 で測ると 34.57 dB (-2.84 dB)。本実装 PLY は splat eval q8 で 36.47 dB、brush 評価器で 35.58 dB (-0.88 dB)。同じ評価器の中で比べると、splat eval では本実装 +1.90 dB、brush 評価器では本実装 -1.82 dB。どちらの評価器を『公式』にするかで優劣が入れ替わる。splats は brush 284,151 / 本実装 485,825 (1.71×)。
2026-09-seminar05-milestones M7 のフォローアップを実施した。**Part 1 (12.5k n=3 再計測)**: `2026-08-30-finalv2-12500-r{1,2,3}.toml` (final-12500-r{1,2,3}.toml の複製、backend flag 無指定で S4b flip 後の default = ssim_reduce=Gpu を含む全採用施策込み) を実行。各 run の `[backend] BackendConfig {...}` ログ行で `ssim_reduce: Gpu, radix_scatter: SimdBallot, refine_scratch_persist: true, refine_direct_write: true` を確認、AC 電源・pgrep 空・binary sha256/git rev 不変 (`c804b349...`/`9bb4ea5`) を series 前後で確認。**as-measured mean は 130.657s (σ1.727%)** — S4b flip で速くなるはずが M7 (124.39s) より遅いという逆方向の結果になった。追加調査で、(1) 10s 間隔 load sampler が r1 window 内で 5.77 まで load1 上昇 (iter6000-7000 相当のタイミング)、r2 window 内でも 4.22 まで上昇、(2) old M7 (r2-r4) と new (r1-r3) の 1000-iter segment ごとの ms/iter を突き合わせると iter0-3000 は new が -4〜-9% 速い (S4b の効果と整合) のに iter3000-12500 は new が一貫して +1.8〜+12.0% 遅い、(3) 実行後の `ps aux` で Finder (147%CPU)・別プロジェクト (otksynth) の Rust バイナリ・音声処理プロセスの実存を確認、という 3 系統の証拠が「同時実行された無関係なユーザープロセスによる session 汚染」を裏づけた。既存の汚染判定規約 (`p3-tier1-bit-exact.toml` §5「load 証拠 AND 自 arm 内 3σ 超」) はこの事例 (3 run 全体が相関して底上げされ、単一の outlier が無い) を検出できない構造的な穴であることも判明した (§2 に規約拡張案を記載)。**同日の paired control 2 本 (S4b gate on-arm 122.768s、`p3-refine-nondrain` off-arm 122.6467s — 後者は refine_gpu_snapshot という no-op field 追加のみの差で本 session の HEAD と事実上同一コード) が相互に 0.13% で一致**しており、この 2 点を「現在の真値」の推定として採用し、milestones.md の「現在地」は上書きしない。brush cross-eval q8 PSNR (final.ply への `splat eval` 実行、load 非依存) は 3 run 平均 **36.289dB** (M7 の 36.249dB から +0.04dB、ノイズ帯)。avg splats (trapezoid 積分による自前算出) は 321,011 (M7 の 321,637 と 0.2% 差で一致、算出法の再現性を裏づけ)。msplat 等価 gap は control 値 (122.768s) ベースで **0.745×** (旧 0.755×)、throughput は **0.916×** (旧 0.926×) とわずかに改善。Pareto v3b (`docs/figures/pareto-v3b-msplat-lego-final-stack-v2.png`) は 12.5k 点の x 座標を control 値、y 座標を finalv2 の brush cross-eval 実測に更新 (両者は異なる run 由来なので script docstring に明記)。**Part 2 (多 scene breakage screen)**: 2026-08-30 に採用された M4 (radix simd_ballot)・A7 (refine 3-pass 削減)・S4b (ssim_reduce=gpu) の 3 施策は全て Lego 12.5k gate のみを根拠にしており、他 scene での検証が無かった。`p1-axis1-phase-g-pareto-landscape.toml` §2 (G.3-alone 30k recipe、2026-05-25、[trainer]/[refine]/[adam] 節が現行 config と完全一致することを diff で確認済み) を baseline に、ficus (227k splats)・materials (355k splats)・drums (998k splats、Lego 407k の 2.5 倍で 3 施策が splat 数 non-uniform に依存する経路を初めてテストする scene) の 3 scene を n=1 で再計測した。**ΔPSNR は ficus -0.020dB / materials -0.027dB / drums -0.010dB で、いずれも `a-10-variance-baseline` の σ±0.32dB (Lego 30k での run-to-run noise floor) の 1/10 以下** — 3 scene とも退行なし。M4/A7/S4b はいずれも理論上 PSNR に影響しない施策 (M4: sort parity bit-exact、A7: 書き込みロジック不変、S4b: gradient 非変更) のため、この結果は「今回の 3 施策の改善効果」ではなく「壊れていないことの確認」として設計通り。Δsplats も ficus +0.32% / materials +1.50% / drums -0.31% と小さい。wallclock は ficus (load 9.6-32.6 で終始汚染)・materials (load 7-27 で終始汚染) は方向感のみ (旧比 ≥3.7×/≥4.4× 高速化) だが、**drums は iter 27000 まで load 0.8-5.5 とほぼクリーンで 3936s→687.85s = 5.72× 高速化を実測**、Lego の 2.5 倍規模の scene でも大幅改善が維持されることを確認した。
Lego で判断された今日の最適化候補が drums (998k splats @30k、Lego の 2.5倍) でも同じ share 構造で有効かを判定した。drums 12.5k を Lego v2 と同一 regime (submission=per_kernel/forward_submission=per_stage/pipelining=off) で 1 run 実測した結果、<strong>per-kernel share は Lego v2 とほぼ同一</strong> (backward_raster 40.09% vs 40.07%、adam 15.52% vs 15.28%、rasterize 14.94% vs 14.13%、ssim 12.75% vs 13.12%、radix 11.37% vs 12.01% — 全 kernel で Δ≤1.5pt)。<strong>splat 数が 1.85倍 (in-window 748,708 vs 404,652) 違っても share 順位・構造がほぼ動かない</strong>という結果は、Lego で優先度付けした施策 (M3 系 backward・M4 radix・S4b ssim 等) の相対重要度が drums でも維持されることを示唆する。<strong>ただし絶対 ms/iter の比較は binary vintage 差で汚染されている</strong> — 比較対象の Lego v2 は commit a446f2c、drums は HEAD 3db33a8 で、間に S4b (ssim_reduce=gpu default flip) と C2 計装 (全 CB へ kernel timestamp 収集追加) が入っている。splat 数と無関係なはずの ssim_fwd_grad が 1.446倍 (1.202→1.738 ms/iter) 増えている一方、全 9 leaf kernel が揃って 1.17〜1.93倍という比較的均一な増加を示しており、これは<strong>純粋な splat-count scaling では説明しにくく、binary vintage (S4b/C2) 由来の系統的な底上げが乗っている可能性が高い</strong>。よって「share の相対構造」は信頼できるが「ms/iter の絶対値・scaling 係数」は次ラウンドで Lego 側も HEAD で撮り直すまで確定できない。
backward_raster (per-kernel share v2 で 40.07%、単独最大) を per-pixel 構造を保ったまま削る候補を 6 件監査した (段 1)。すでに勝者化済みの施策 (SIMD group reduction / W1a warp sparse skip+exp-skip / last_contributor 早期終了) と禁忌リスト (Tg staging、f16、SIMD prefix、reduction) を除くと、残る候補はいずれも大きい Δ を期待できず、harness の実測分解能 (~1%、M2 Tier1 が -1.11% を「判定不能」、M5a が -0.055% を「null」と判定した床) 前後に収まる可能性が高いという見立てになった。最有力候補として選んだのは <strong>M8: `rasterize_backwards_simd` の 9 atomic emit を lane 0 の 1 lane だけでなく lane 0..8 の 9 lane に分散発行する</strong>変更 — `simd_sum` が 9 成分の合計を全 32 lane に broadcast する性質を使い、emit する (address, value) の集合を一切変えずに発行 lane だけ変える (新しい算術を持ち込まない「弱い意味で bit-exact」な変更)。`BackendConfig.raster_backward_atomic` (`lane_zero` default / `spread_lanes`) で flag-gate し、専用 PSO は現行 default combo (`Simd` + `LastContributor` + `WarpAny`) にのみ追加した (他 combo は validate warning 付きで silent fallback、既存の `raster_backward_sparse` と同じ規約)。**正しさ**: 24-splat 合成 tile の単一 pixel fixture で bit 一致 (新規 test 2 本、`backward_atomic_spread_byte_equality_single_pixel` / `_parity_simd`)、実 checkpoint (12500 iter 生成、408,469 splats、PSNR 36.202 dB) での `splat bench --parity` は候補比較が FAIL することがあるが、**同じ config を自分自身と比較する self-check でも全く同じ頻度・同じ max_abs_diff (通常時 5.245e-5 / 稀に 1.469e-4) で FAIL/PASS する**ことを確認し、これが M8 固有の誤差でないことを実証した (発生機序自体は atomic 順序 self-noise / `sorted_idx` tie-order 非決定性のどちらとも確定できておらず、§4 callout に切り分けの詳細を記す)。**性能 (whole-iteration)**: 短時間 replay bench (12.5k 相当 checkpoint、iters=50×repeats=3、pipelining=off、production regime = submission/forward_submission ともに `chained`) を off/on 交互 3 pair 実施したところ、**3/3 pair で on が遅い**(median ms/iter: 13.564→13.731 / 13.600→13.812 / 13.595→13.753、平均 13.586→13.765 = **+1.32%**、GPU busy 平均 10.752→10.969 ms/iter = **+2.02%**)。**性能 (backward kernel 単体 gpu_ms)**: production regime では `ts_backward_raster` の `gpu_ms` が非ブロッキング harvest の帰属漏れで 0 に落ちる (既知の限界、`docs/architecture/backend-and-compiler-conventions.md` §4) ため、p3-kernel-share-post-s3 C1 と同じ `submission=per_kernel`/`forward_submission=per_stage` regime で同一 checkpoint を計測した。**`ts_backward_raster` gpu_ms/call: off 4.2016ms → on 4.3670ms = +3.94%** (150 call = 3 repeats × 50 iters、両 arm とも n=3 の repeat 内 σ ≤0.4%) — whole-iteration の +1.32%/+2.02% が「kernel 自体が遅くなったこと」に直接帰属できることを、share からの推論ではなく実測で確認した。advisor が指摘していた「lane 0 の 9 atomic は既にハードウェアがパイプライン化している可能性があり、spread の win は nil かもしれない」という懸念が的中し、むしろ select chain のオーバーヘッドがわずかに上回った形の **小さいが一貫した regression**。**NO-GO、default は `lane_zero` のまま変更しない**。12.5k full gate 用 config 6 本は `splat check` で deserialize 確認済みだが、bench screen の時点で明確な regression のため実行しなかった。`cargo build --release` + `cargo test --workspace --release` (全 175 test、新規 2 本含む) は全 pass、default 動作 (既存挙動) は無変更。
`p3-kernel-share-post-s3.toml` §4/§8 の宿題 (「残差は既存計装では分解不能、実装後も 12.5k 実測がまだ無い」) を、`2026-08-30-c2-12500-depth2-prof.toml` (M4+A7 default 込み、S3 gate arm B と [backend] bit-exact) の 1 run で埋めた。<strong>reliable=true / dropped=0 / kernel_invalid=0 / sum/union=1.000000x</strong> — 信頼性ゲート健全、全列使用可。wall 124.75s / busy 113.627s (91.1%) / sync-tax 11.126〜11.129s は `p3-final-stack` の n=3 mean (124.393s, σ0.756%) の guard 内 (n=1 の点推定として妥当)。<strong>Σcb_gap=11.085s が sync-tax 全量の 99.6% を説明</strong>し、`p50×n` (band 別合計 7.244s) と `mean×n` (11.081s) の差 3.837s を refine tick 由来の外れ値と読むと、<strong>残差 (通常境界) 7.2〜8.1s (5.8〜6.5%) / refine tick drain 3.0〜3.8s (2.4〜3.1%)</strong> にブラケットできる。refine 側は `ts_refine`(2.869s)+`ts_opacity_decay`(0.185s)=3.054s の独立 host 実測が下限とほぼ一致し、クロスチェックが成立した。<strong>旧 3 分解 (refine 6.26s / encode(B) 3.41s / 残差 4.54s、旧 sync-tax 全量 14.206s) との整合</strong>: 旧「残差」+「encode(B)」= 4.54+3.41=7.95s ≈ 新「通常境界」7.24s (wall が 151.70→124.75s に縮んだ分を割り引けば近い) — <strong>旧 encode(B) バケツは独立した加算成分ではなく、非重複だった encode コストが host-late として `cb_gap` に同じ形で現れていた</strong>と判明し、旧 3 分解を「refine drain / それ以外 (通常境界)」の 2 分解へ訂正する形になった。<strong>帰属の結論: 通常境界の bubble は host-late が支配的、driver 処理 (`drvproc`) と GPU キュー待ち (`handoff`) は定常帯で中央値がほぼゼロ (headroom 薄い)</strong> — task が例示した「handoff → CB 統合」は主因ではないと実測が明示的に否定した。
2026-09-seminar05-milestones M7 を実施した。(1) **12.5k full run 独立 n=3**: `2026-08-30-final-12500-r{1,2,3}.toml` を単純 3 repeat (off arm なし、全 [backend] flag は default 任せ = M4 radix_scatter=SimdBallot + A7 refine_scratch_persist/refine_direct_write=true 込み) で実行。r1 (131.84s) が r2/r3/r4 (123.34/124.69/125.15s) から外れて見えたため、advisor レビューを経て診断用の r4 を追加実行した結果、**r1 は script 再起動時に load sampler window ログが truncate され窓内記録が皆無**という house 規約 (p2-msplat-parity-final §7「事前 gate だけでは不十分、窓内記録が必須」) 上の欠陥を抱えていたことが判明し、r2/r3/r4 (全 run とも window 記録あり、load 正常) を正式な n=3 として採用した。**mean 124.393s (σ 0.756%)** — A7 gate on-arm mean 124.807s を -0.33% で独立再現しており、この近さ自体が両 session の健全性証拠になる。r1 込みの参考値 (n=3 リテラル/n=4 全部) も §1 に残す。(2) **per-kernel share v2**: `2026-08-30-c1v2-12500-off-prof.toml` (submission=per_kernel/forward_submission=per_stage/pipelining=off、M4/A7 default 込み) を 1 run。leaf gpu_ms 合計 114.508s は busy union と exact 一致。radix share 26.40%→12.01% (絶対 -63.25%、M4 gate の per_stage 補助計測 -63.7% と独立一致)、backward_raster が単独最大ブロックとしてさらに優位 (33.86%→40.07%)。詳細は `p3-kernel-share-post-s3.toml` §6 に追記。(3) **累計 ablation**: p2 の 8 段 (Phase0 766.07s → S3 151.70s) に M4 (127.53s、-14.9%) / A7 (124.81s、-2.15%) / M7 独立再計測 (124.39s、-0.33%、ほぼ noise level) を継ぎ足し、Phase 0 比 **-83.76%**。(4) **msplat 等価再比較**: p2-msplat-parity-final の計算手順を最終値で再計算。gap 分母は継続性のため block1 n=2 mean (164.69s) を維持 (msplat 側は再実行していない)。**wallclock gap 0.927×→0.755×**。throughput は avg splats を新 4 run の trapezoid 積分から自前算出 (321,637、旧値 322k とほぼ一致し手法の妥当性を裏づける) して **1.135×負け→0.926×勝ち** (ただし msplat 側 avg splats ~165k は p2 からの借用値で本 session では再導出できておらず、逆転が成立するのはこの借用値の誤差が +8.0% 未満の場合に限る、§4 callout 参照)。brush/white PSNR は既存 final.ply に対し `splat eval` を回して再計測し (新規 GPU 学習 run は不要)、両 convention とも旧値からほぼ不変 (brush +2.01dB / white -1.11dB) — M4/A7 は PSNR trajectory に理論上影響しない施策なので想定どおり。matched-iteration (30K vs 30K) / matched-wallclock (旧 13.3k 点) / matched-PSNR(brush) の旧 6.0k 点 / energy は**新規 GPU run が必要なため本 session では再計測せず**、旧スタック値を明示ラベルで carry forward するに留めた (外挿スケーリングによる偽の精度を避ける、advisor レビュー指摘)。(5) **Pareto v3**: `make_msplat_pareto.py` の入力を msplat 等価比較 4 点 Pareto curve (p2-msplat-parity-final §10 の未実施項目) に更新し `docs/figures/pareto-v3-msplat-lego-final-stack.png` を生成。12.5k 点のみ最終スタック値、他 3 点 (6.0k/13.3k/30k) と msplat は旧スタック値のまま明示ラベル。
per-kernel share v2 で 2・3 位の rasterize forward (14.13%) と adam (15.28%) を監査した。forward は 5 候補 ((a) simd 早期終了 (b) barrier 数 (c) 出力 packing (d) conic/color の float4 化 (e) occupancy)、adam は 3 候補 ((f) 帯域床の再計算 (g) buffer/dispatch 数 (h) visible-only skip) を列挙した。<strong>本 finding の核は (f)/(d)/(c) の判断根拠になる byte-accounting を自前で初めて行ったこと</strong>: adam は 1 splat あたり 59 element (means3+log_scales3+rot_quats4+raw_opacities1+sh_coeffs 16×3=48) × 28 byte/element (read: grad+m+v+param 16B、write: m+v+param 12B) = 1,652 byte/splat を動かす。M7 final-stack (r2-r4) の平均 splat 数 321,637 (trapezoid 積分による自前算出値、p3-final-stack) を使うと 1 iter あたり 531.3MB、per-kernel share v2 の `ts_adam` 1.400ms/iter (v1 1.438ms/iter) と組み合わせると実効帯域 <strong>369.5〜379.5 GB/s = この M4 Max (14-core CPU/32-core GPU、410GB/s 公称、Apple 公式値で確認済み) 比 <strong>90.1〜92.6%</strong> — ほぼ飽和</strong>。**この計算で「平均 N」ではなく「最終 N (407,028)」を使うと 480.3GB/s = 117% という物理的に不可能な値が出る** — gpu_ms/iter は 12,500 iter 全体の平均であり、splat 数は 0→407k に増える過程の平均 (321,637) と対応させないと過大評価になる、という罠を本 finding で明示した (自己検算)。forward は同じ手法で Splat2D 36B/pair の staging read (avg pairs ≈765,900、407,267-splat checkpoint の実測 969,838 pair を平均 splat 数比でスケールした概算) + 出力 3 buffer 24B/pixel (640,000 px 固定) ≈ 46.0MB/iter を `ts_fwd_rasterize` 1.295〜1.320ms/iter と組み合わせると実効帯域 <strong>34.9〜35.5 GB/s = 410GB/s 比わずか <strong>8.5〜8.7%</strong></strong> (pairs 概算が 10 倍近くずれても帯域律速には転じない、桁のオーダーとして頑健)。この非対称 (adam は帯域飽和、forward は帯域 1 割未満) が両 kernel の残余候補の見立てを直接決める: adam は (h) visible-only skip 以外に理論上削る余地がなく、forward は (c)/(d) のような帯域削減系候補が原理的に低 payoff で、ALU/occupancy 側の余地を探すしかない。旧 <code>2026-08-next-phase-tasklist.md:46</code> の「adam 帯域床 65.6%」の出典を `docs/strategy/raw/*.json` で検索したが adam 固有の帯域算出は見つからず、同一の 65.6% は `p2-counter-session.toml` の <strong>非 production per_kernel regime run の GPU busy% 列</strong>にのみ存在する (`2026-09-seminar05-milestones.md:19` 自身がこの規模の同数値を「使えない」と注記している) — 誤用と断定する証拠はないが、今後 adam の帯域到達率として引用するのは避け、本 finding の 90〜93% を正とすべき。forward の (a) は backward の W1a (simd_any による reduction/atomic emit の skip) と構造が異なる: forward は per-splat の reduction/atomic を持たず、per-thread `!done` 条件による loop 早期脱出がハードウェアの execution mask 収束と等価な効果を既に持つため、明示的な `simd_all(done)` 追加は原理的に redundant (期待 Δ ≈0)。(b) は `num_done_atomic` の読み手が loop 先頭の 1 箇所のみ (`grep -rn num_done` で確認) であることを利用し、初期化直後の 2 本目の barrier (rasterize.metal:106) を安全に削除できる (bit-exact、単調増加のため未同期時は過小評価のみで正しさに影響しない) — ただし forward が ALU-bound という上記結論と整合的に期待 Δ は harness 分解能未満と判断した。(c) 出力 packing は f16 storage 禁忌 + backward が final_T を f32 精度で必要とするため機会なし。(d) conic/color の float4/SoA 化は forward が帯域 1 割未満という結果から低 payoff、producer (project.rs) にも触れる高工数で見合わない。(e) occupancy/register は backward 監査と同じツール限界 (Xcode GPU Frame Capture 相当が本環境に無い) で直接観測不能、TG memory 使用量 (9,220B/32,768B) からは非律速と推測されるに留まる。AIR level では `-ffast-math` 相当の `air.fast_exp.f32` が既に使われていることを確認した (`shader_fast_math` の default が `true` = MTLCompileOptions default であるため) — 「fast exp に切り替える」候補は既に default で実施済みであり追加の余地なし。**結論: bit-exact-class で harness 分解能を超える候補は forward・adam いずれにも残っていない。段 2 (実装) は task 記載の <1% 省略条件に該当するため実施しなかった**。
M3 (per-splat backward, brush PR #401 型) の GO/NO-GO 閾値「backward_raster share ≥ 25%」を判定した。post-S2/S3 kernel (hierarchical radix scan / resident binning) を submission=per_kernel/forward_submission=per_stage/pipelining=off (per-kernel breakdown が測れる唯一の regime) で 1 run 実測した結果 <strong>backward_raster (+project_back 統合) share 33.86%</strong> で <strong>閾値を大きく超過 → M3 は GO</strong>。<strong>share × 0.25 (brush の -25% 主張をそのまま適用したナイーブな期待値) = 8.47%</strong>。ただしこれは本 run の GPU busy (68.9%、production の 91.3% とは別 regime) に対する share であり、production (depth2 default) の wallclock に対する期待 Δ は <strong>33.86% × 91.3% × 0.25 ≈ 7.7%</strong> とみるほうが妥当 (kernel 自体の gpu_ms は submission wrapping にほぼ不変という counter-session の事後検証はあるが、n=1 点推定であることと合わせて上限値として扱う)。<strong>pre-S2/S3 (counter-session) との比較では share 構成はほぼ不変</strong> (backward_raster 33.6%→33.86%、radix 26.3%→26.40%、rasterize 11.9%→11.64%、adam 13.8%→12.68%、ssim 10.0%→10.95%) — S2 のhierarchical scan は「radix の CB/wait 数」を畳んだだけで kernel 自体の GPU 時間配分は変えていない、という roadmap の当初の想定を実測で裏づけた。C2 は M0 の並行会計訂正 (encode(B) 4.66→3.41s、残差 3.28→4.54s、nested label 二重計上の是正) を踏まえ、<strong>残差 4.54s (depth2 sync-tax の 32%) を driver 投入 latency と CB 間 gap に分解しようとしたが、既存計装 (`gputime.rs`) は `kernelStartTime`/`kernelEndTime` を objc bind しているのみで収集しておらず、per-CB の生 interval 列も外部に露出していない</strong> ため<strong>分解不能</strong>と判明した。file:line 付きの追加案を §C2 に残す (実装はしていない、GPU run はこれ以上起動していない)。
M3 の実装フェーズ (spec: docs/strategy/2026-09-seminar05-milestones.md) を完了した。**新 kernel `rasterize_backwards_per_splat` を既存 3 kernel (Original/Simd/Tg) と並存する別 entry として追加**し、`BackendConfig.backward_scheme` (`per_pixel` default / `per_splat`) で配線した。**正しさの証拠は 2 層で強い**: (1) unit-level — 単一 pixel fixture で `Original`(FullRange,Off) と bit 一致、multi-pixel fixture (32×32/24×24) で `abs/rel 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/log_scales/rot_quats/raw_opacities/sh_coeffs` の全 grad tensor が **既存 backward variant (Original vs Simd/Tg) と同じ `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/iter) は現行 default (per_pixel = Simd+WarpAny+LastContributor、15.354 ms/iter) 比 **+34.1%** 遅いだけでなく、**W1a/LastContributor 等の最適化を一切持たない per_pixel (Original+FullRange+Off、17.681 ms/iter) 比でも +16.5% 遅い**。GPU busy ms/iter は per_splat 17.753 に対し per_pixel(unopt) 14.914 で、sync-tax はどの arm も ~2.8〜2.9ms/iter で揃っている — つまり待ち時間の付け替えではなく **transposed loop nest 構造そのものが Apple GPU 上で不利**という決定的な結果になった。brush が報告する backward -25% とは逆方向。**副次効果 (atomic 順序依存の消失) は実証できた** — per_splat 自身の self-noise は max_rel 5.1e-6 (32×32) / 完全 bit-exact (24×24) で、atomic 版 `Original` の self-noise (4.5e-5) の 1/9 以下。**この regression で 12.5k trainer 統合 gate (wallclock Δ / 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 (既存挙動) は無変更。
第 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/24×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/rtol=1e-4) 内で PASS、`sorted_idx` は既知の非決定性 (0.222% 差、非 gate)。(4) 4-way bench (median ms/iter, n=3, warmup=10/iters=50/repeats=3): per_pixel (default, σ0.59%) **13.548** / per_pixel unopt (σ0.34%) 15.701 / per_splat v1 (σ0.12%) 18.787 / **per_splat_tg256 (σ0.35%) 17.994**。tg256 は v1 比 **-4.22%** — §3 が予告した 3 効果 (barrier 総数 4.5 分の 1 / thread-iteration 効率 1.78 分の 1 悪化 / 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` は無変更。
tasklist A5 (radix は帯域 36% の latency 律速と算術証明済み) の実装検証。既存 O(lid) 逐次 threadgroup memory scan を simdgroup ballot 2 段化に置換し、BackendConfig `radix_scatter` の enum variant `simd_ballot` として追加、**2026-08-30 M4 GPU gate で default に採用**。sort parity は unit test 3 本 (境界サイズ 0/1/255/256/257/1234/100000、ties 多発 n=5000、3 種の radix_scan 実装すべて) と本番規模 (407,267 splats) `splat bench --parity` の両方で bit exact PASS。**12.5k Lego 同一 session 交互 A/B n=3 (off-r1→on-r1→off-r2→on-r2→off-r3→on-r3、独立 10s load sampler で汚染監視、binary sha256 は series 前後で不変) で train elapsed 149.883 → 127.530s = -14.9%**、3 pair 個別 (-14.72% / -15.15% / -14.87%) が高い一貫性を示し、有意閾値 max(2σ_off,1%)=1.18% の **12.6 倍**という大差で通過。σ は off 0.59% / on 0.79% (非対称比 1.34×、汚染の署名である 3× を大きく下回る)。**PSNR guard も pass** (on mean 36.143 dB ≥ off mean 36.121 dB − 0.05 dB、Δ +0.022 dB、両 arm とも config header の絶対 guard 36.202±0.1 dB にも収まる)。final splats は on 408,084 / off 409,363 で -0.31% (既存 atomic 非決定性 chaos の範囲内)。session 開始時の ambient load 18.86〜22.8 (Spotlight `mediaanalysisd`/`mds_stores` 再インデックス、reboot 後) という p2-s3 が破棄基準にした汚染クラスの中で実施したが、同一 session 交互設計と 3 pair の高い一貫性 (レンジ 0.43 pt) がこれを吸収したことを §0 で示す。**結論: 採用。`RadixScatterKind::default()` を `SimdBallot` に flip、`cargo test --workspace --release` 全 pass**。
A7 (refine の 3-pass 削減) を実装・gate した。(a) <code>refine_scratch_persist</code>: compact pass の scratch <code>Vec</code> 30 本を <code>RefineState</code> (新設 <code>RefineScratch</code>) に永続化し <code>std::mem::take</code> で借り出し・tick 末尾で書き戻す。allocation の出所が変わるだけで計算は 1 つも変えない。(b) <code>refine_direct_write</code>: compact 書き込み先の抽象 <code>Dst</code> (<code>Vec</code> か Metal buffer 生ポインタ) を導入し、<code>direct_write = true</code> のとき新規 <code>Vec</code> を一切作らず compact loop が <code>param.*</code>/<code>adam_state.*</code> に直接書く。実装中に見つけた subtle な罠: Clone の複製先 / Respawn / Split の子スロットは旧実装では「新規 0 埋め <code>Vec</code>」から無料で Adam m/v = 0 を得ていたが、direct 経路は <strong>stale データが残っている可能性のある live buffer</strong> に書くため、この暗黙の 0 を前提にできない — <code>zero_adam_at</code> ヘルパーで明示的に 0 を書くよう修正した (無修正だと A7(b) 単体で MCMC 論文の「新規 slot は Adam fresh start」不変条件が壊れていた)。不変条件 I (<code>[num_splats, capacity)</code> は常に 0) は direct 経路でも <code>zero_tail</code> による <code>[n_new, n_write)</code> の明示 0 埋めで維持する。<strong>gate: 12.5k n=3 交互 A/B (2回目 series、a7v2-12500) で Δ -2.149% (閾値 max(2σ_off,1%)=1.612%)、PSNR +0.0197dB (guard 内)、3/3 pair 一貫 (on<off)。1回目 series は load 汚染 (6 run 中 3 run に load1 スパイク) で棄却</strong>。default flip 実施: <code>BackendConfig::default()</code> の両 flag を <code>true</code> に変更。field 単独の <code>#[serde(default)]</code> は付けない (bool 型に付けると <code>bool::default()</code>=false に固定され struct 側の true を上書きするため — <code>target_cache</code>/<code>shader_fast_math</code> と同じ規約)、これは 1 iter smoke で config 省略時に <code>refine_scratch_persist: true, refine_direct_write: true</code> が実際に解決されることを確認済み。<code>cargo test --workspace --release</code> 全 pass (0 failed)。
refine tick 頻度を <code>[refine] every</code> 100→200 に変更する hyperparameter 実験 (非 bit-exact、学習 dynamics が変わる)。12.5k Lego n=3 交互 A/B (off=every100 baseline / on=every200 candidate、他の refine パラメータ (<code>stop_iter</code> 等) は不変) で、PSNR guard (n=3 で on mean >= off mean - 0.05dB) と最終 splat 数の変化を主眼に計測した。<strong>PSNR Δ -0.421dB で guard を約 8.4 倍超過 — 不採用</strong>。wallclock は Δ -25.6% と大幅短縮したが、tick drain 半減 (sync_iters 121→61、期待帯 -1.2〜-1.5% 相当) は寄与のごく一部に過ぎず、大半は densification 予算削減による最終 splat 数 -35% (407.7k→266.7k) の副作用。<code>refine.every</code> は tick drain の独立ノブではなく、growth/clone/split イベント頻度と opacity decay 累積量 (`opacity_decay_rate` は refine cadence で適用) を同時に変える hyperparameter であることが判明した。r2 pair は事前登録条件 (load spike AND 3σ超) を満たし 1 回 retry したが、PSNR guard の判定には影響しない (PSNR は決定論的、load は wallclock のみに影響)。<strong>default config の書き換えはしない — 採否はユーザー判断待ち</strong>。
`p3-c2-bubble-attribution` §6 施策 #4 (refine tick drain の non-draining 化、期待 -1.5〜-2.5%) を検討・実装した。<strong>advisor との構造分析で「drain 自体は構造的に必須、縮められるのは中身」と reframe</strong>: `Depth2Pipeline::step` の `B_it` 統合 CB は Adam encoder で param/adam 全 15 buffer を書き換えるため、`refine()` の snapshot read はこの書き込み完了 (`wait(B_it)`) を待たないと race になる。task が提示した候補 (a) tick を `B_it` commit 直後に前倒し、(b) 候補選定だけ先に走らせる 2 段化、(c) 再充填コスト削減 は、いずれも「`B_it` の GPU 実行中に host が snapshot を読む/書く」という同じ race を踏むか、staleness (1 tick 分古い grad/param を使う意味論変更) を受け入れる必要があり、後者は `p3-refine-every-200` (densify 予算副作用で PSNR guard 8.4 倍超過、棄却) と同種のリスクを持つ。一方、advisor が提案した第 4 の道 (host memcpy を GPU blit に置き換えて `B_it` CB 自体を延長する) は staleness を一切受け入れずに host の逐次コピーコストを消せる — <strong>これを `[backend] refine_gpu_snapshot` として実装した</strong>。snapshot 対象 15 buffer のうち `raw_opacities` (opacity decay が blit 後に書き換える) を除く 14 buffer を、Adam encoder 直後に追加した 1 blit command encoder (14 `copy_from_buffer`) で GPU 側 mirror buffer にコピーし、`refine()` はその mirror を読む。安全性は 2 層: (1) encode 時点で `pipeline::refine_tick_wants_gpu_snapshot` が「Adam が同一 CB 内で完了するか (`!grad_rmw_pending`)」「`wait(B_it)` 後に MCMC noise/relocation がこれらの buffer を触らないか」を判定し、条件を満たさない tick では blit を encode しない、(2) `refine()` 側は `gpu_snapshot_ready_for.take() == Some(it)` のときだけ消費し、iteration が食い違えば (万一 (1) の判定が pipeline とズレても) 無条件に host snapshot へフォールバックする — 誤った iteration の値を使うバグが構造的に起きない設計。`cargo test --workspace --release` 全 pass (0 failed、新規 5 test 込み)。1000 iter smoke (Lego) で crash なし、`refine_gpu_snapshot: true` が実際に解決され `ts_refine_snapshot_blit` が refine tick 数 (6 回) と一致する回数だけ発火することを確認。<strong>2026-08-30、main 上で 12.5k n=3 交互 A/B gate (off→on×3) を実施</strong>: train elapsed (internal timer) off mean 122.6467s (σ 0.330%) → on mean 122.3567s (σ 0.301%) = Δ **-0.2365%**。有意閾値 max(2σ_off,1%)=1.000% の **24%** にしか届かず、pair 一貫性も 3 組中 2 組 (r1: -0.788%, r2: -0.082%) が on 優位、r3 (+0.163%) は逆方向という系統性の無い結果。事前の advisor 試算 (-1.2〜-1.9%) が明記した「pessimistic ケースでは不通過もあり得る」を超え、実測は pessimistic ケースの想定 (max(2σ,1%) 近傍での僅差) よりもさらに小さい、実質ノイズ水準の null 結果だった。PSNR は +0.0553dB で guard (-0.05dB 以内) を pass するが、wallclock が閾値に遠く及ばないため<strong>棄却確定、`refine_gpu_snapshot` の default は false のまま維持、code は変更しない</strong>。汚染判定 (`p3-tier1-bit-exact.toml` §5 の事前登録条件、load spike AND 3σ超 の AND) は off-r1 の load1 window mean が他 run よりやや高い (2.41 vs 0.80-1.38) ものの偏差 1.07σ (<3σ) で条件不成立、かつ off-r1 を除外しても Δ は -0.060% とさらに小さくなるだけで結論は変わらないため retry は実施しなかった。
C2 施策 #1 (post-backward host 仕事を backward CB shadow に配置) を `[backend] host_schedule` flag として実装し、12.5k n=3 交互 A/B gate を実施した。**棄却 — ただしどの尺度で見ても符号は on≥off で一貫**: 採用セット (r1→r4 置換) の点推定は +5.63% だが、これは on-r4=141.77s という単一の大外れ値に支配された数字であり (on-r4 を除くと +1.8%、r1 込みの retry 前でも +1.02%)、σ_on 6.36% の広さを踏まえると真の効果量は ~1〜2% (harness 分解能付近) で null〜わずかな悪化とみるのが妥当 (`p3-tier1-bit-exact` v1 が経験した「単一の汚染値が代表値を膨らませる」パターンの符号違い版)。r1 pair は series 独立 load sampler で load1 max 7.91/8.90 (LOAD_LIMIT 6.0 超) を検知し事前登録条件 (i)(ii) を満たしたため 1 回だけ retry (r4) に置換 — ただし (i) の判定は max ベースで行っており、mean ベースでは off-r1 (mean 2.72) は 1.5×中央値 (3.765) 未満で非該当になる (次回の predecision には mean/max のどちらで評価するか明記すべき教訓、§8 参照)。retry 後の on-r4 (141.77s) はさらに大きな外れ値だが、走行中 load1 は終始 clean (mean 1.64 / max 3.19) — 事前登録条件 (i) load 証拠が不成立のため追加 retry はせず (`p3-tier1-bit-exact` §5 の教訓通り、条件 (ii) 単独での retry 連鎖を回避)。discarded r1 pair 自体は on<off (on が速かった) — 「3/3 一貫」は採用セットに限った話で、破棄分含む 4 pair 全体では 3/4 が on>off。ms/iter trace は on-r4 で iter 2000 以降一貫して高い (discrete spike ではなく持続的) — A7 §7 off-r3 と同型の GPU thermal 蓄積の可能性はあるが host_schedule 由来と特定する根拠はない。全 pair とも off→on の順で実行 (ABAB、ABBA 均衡化なし) — on arm は常に「温まった後」の機体条件で走っており、末尾の on-r4 が最遅であることと整合するが、同構造の A7 gate では on 側が一貫して速かったこともあり主要因とは考えにくい。棄却により `.rs` は一切変更していない。
SSIM の walk 方式を選べる BackendConfig `[backend] ssim_walk` (`per_channel` default / `float4` / `float4_rcp`) を実装し、shader (`ssim_forward_float4`, `ssim_backward_rcp`) と Rust 配線 (`SsimEvaluator`, `Trainer`, `apply_backend_config`, result.toml item) を完結させた。<strong>stage 1 (float4 化 forward) は K=7/K=11 の単体 test + 本番規模 (407,267 splats) `splat bench --parity` の両方で byte-exact</strong> — PSNR risk がゼロの再挑戦候補として残す。<strong>stage 2 (逆数共有 backward) の REL_TOL は実測ベースで 2e-4 に確定</strong> (K=7 max_rel=8.4519e-5 / K=11 6.3679e-5、旧 2-divide 実装の 8.28e-5 とほぼ同水準 — fast math 近似逆数の精度floorが支配的で除算回数削減の理論的優位はほぼ観測できなかった)。3-way replay bench (`submission=per_kernel` で ssim label を分離) では float4_rcp の ssim label gpu_ms が per_channel 比 -20.8% (758.92→601.06ms/600calls) と明確に縮小したが、<strong>12.5k Lego 同一 session 交互 A/B n=3 gate (「採用候補の最終形 = float4_rcp」を一括計測) では PSNR guard に抵触し不採用</strong>: on mean 36.1327 dB (36.156/36.170/36.072) vs off mean 36.2133 dB (36.256/36.204/36.180)、Δ -0.081 dB は guard 閾値 -0.05 dB を超過、3 pair 全てで on<off の完全分離という系統的な質低下だった。wallclock は Δ -0.055% (off mean 126.954s → on mean 126.884s) で有意閾値 max(2σ_off,1%)=2.53% に届かず null。§5 で示す通り、ssim の budget share (11.80%、p3-kernel-share-post-s3) と isolated-label 効果 (-20.8%) から予測される wallclock 寄与は ~-2.5% で、この gate の解像度限界とほぼ同水準だった — milestone の期待 delta (-4〜6%) はこの意味で楽観的すぎた。config.rs / ssim.rs の `SsimWalkKind::default()` は `PerChannel` のまま変更していない。
M2 Tier1 の 4 flag (A1 SSIM memset 除去 / A2 work_grad blit 化 / A3 backward uniform set_bytes 化 / A4 lazy C3 scratch) を全 ON/全 OFF の 2 arm にまとめ gate した。<strong>v1 (n=3, 旧 baseline)</strong>: train elapsed (internal timer) off 155.40s (σ 2.56%) → on 147.64s (σ 0.55%) = -4.99%、3 pair 全てで on が速い一貫した方向を示したが有意閾値 max(2σ<sub>off</sub>, 1%) = 5.11% を 0.12 pt 差で下回り不通過。同時に PSNR は on 側で完全分離 (mean Δ -0.065 dB) し task 指定 guard に抵触した。<strong>v2 (n=5, 2026-08-30 M4 radix ballot 採用後の新 baseline 127.4s 上で再 gate)</strong>: PSNR は mean **+0.028 dB**、5 pair 中 on>off 3 / on<off 2 の符号混在で <strong>v1 の系統分離は再現せず、「A1/A2 chained path の静かな壊れ」仮説は反証</strong>された。wallclock は r1 pair の load 汚染 (on-r1 走行中に load1 が 9.09 まで spike) を検知し 1 回だけ再実行 (r6 で置換、元 log は `*-CONTAMINATED-*` として保存) した後の値で Δ **-1.11%**、有意閾値 1.05% を 0.06 pt 差で形式上通過する。しかし①汚染 r1 を生のまま使うと Δ-0.30% (不通過)、②両方の r1 試行を n=6 として残すと Δ-0.15% (不通過) と<strong>1 点の去就で判定が反転する脆い pass</strong>であり、さらに③置換先の r6 自身が事前登録した再実行条件 (自 arm 他値から3σ超) を独立 load 証拠の裏付けなしに 10.3σ で踏む (条件だけでは停止しない除外連鎖になる設計上の欠陥が判明)。advisor レビューの指摘により、0.06pt の脆い pass を根拠に default flip して M7 最終スタック・卒論数値の土台にするのは不適切と判断し、<strong>棄却を維持</strong>した (根拠は v1 の「PSNR guard 抵触」から v2 の「wallclock 効果量 ≤1% で本 harness (n=5) の分解能未満、判定不能」に変わった)。両 gate とも `cargo test --workspace` (A1 sentinel probe / A2+A3 4 組合せ parity / A4 self-heal 含む) は全 pass — 実装レベルの correctness bug は一貫して否定的。<strong>結論: 棄却維持、4 flag の default は変更しない、config.rs は一切触らない</strong>。
1× 工程表 v2 の最終段を通し、卒論 §5 の direct comparison を確定させた。<strong>本実装 Lego 12.5k = 152.68s / msplat 30K = 164.69s (block 1 interleave pair の n=2 mean 同士) で wallclock gap 0.927×</strong> — 2026-08-16 の同一 protocol 実測 2.10× から <strong>2.27 倍の改善</strong>で、初めて convention 非依存の軸で msplat を下回った。<strong>per-splat·iter throughput も 2.62× → 1.135×</strong> と near-parity まで詰まっており、「本実装は workload 形状 (少 iter × 多 splats) で勝っているだけで kernel は遅い」という 2026-08-16 時点の解釈は<strong>もはや成立しない</strong>。エネルギーも <strong>GPU 0.906× / package 0.896×</strong> と反転したが、機構は counter session (低 W × 長時間) から <strong>同 W × 短時間</strong>へ完全に入れ替わっている (W 比 0.704× → 0.978×) — S3 が GPU busy を 77.5 → 91.3% に上げた以上、低 W は原理的に維持できない。<strong>一方 PSNR の matched 断面は convention 依存のまま</strong>: brush では 6.0k (0.313×) で msplat 30K を上回り、white では 30k (2.888×) でも -0.81 dB。roadmap v2 が「msplat native 比 -0.34 dB」と留保していた差は、<strong>30k まで延ばしても self-eval が 36.455 dB で天井</strong>になることから <strong>iter 予算の不足ではなく評価 convention の差</strong>と確定した (Phase H の 36.384 dB 天井とも整合)。よって当該留保は「解消」ではなく<strong>撤回</strong>し、convention 別の 2 断面に置き換える。
1× 工程表 v2 が「S2 後の単独本命」に指定していた S3 を gate し、採用した。S2 までの施策が <strong>CB の数</strong>を減らすものだったのに対し、S3 は <strong>CB の並び方</strong>を変える — iteration N の loss/backward CB (B<sub>N</sub>) を commit したら wait せずに iteration N+1 の forward CB (F<sub>N+1</sub>) を組んで commit し、<code>wait(B<sub>N</sub>)</code> の後の host readback / <code>accumulate</code> を F<sub>N+1</sub> の GPU 実行の影に置く。<strong>12.5k 同一 session 交互 A/B n=3 で 185.21 → 151.70s = -18.1%</strong> (閾値 max(2σ,1%) = 6.7% の 2.7 倍)。<strong>GPU busy 77.5 → 91.3% / sync-tax 3.244 → 1.136 ms/iter (-65%)</strong> で counter session が置いた「busy 100% = 理論上限」への距離は 22.5 pt → 8.7 pt に縮んだ。<strong>1k smoke では busy 65.8 → 72.0% にしか上がらず判定不能だった</strong> — smoke の splat 数 6.8k では forward の GPU 影 (1.06 ms/iter) が image size 固定の host 仕事 (~1.7 ms/iter) を隠しきれないためで、これは <strong>「pipelining の gate は smoke では代替できない」という harness 上の教訓</strong>として残す。残 bubble の内訳も確定した: <strong>refine tick の drain 6.04s (43%) > encode(B) 4.66s (33%) > 残差 3.28s (23%)</strong> — 次の一手が roadmap の「即効ペア (refine capacity スコープバグ修正)」であることが実測で決まった。msplat 同日等価 gap <strong>1.105× → 0.907×</strong>、Phase 0 からの累計 766.07 → 154.0s = <strong>-79.9%</strong> (全て数学的同値の施策のみ)。
`splat bench --config bench.toml` を実装し、同一 config n=10 replay で <strong>σ_replay = 0.234 ms/iter (mean 28.339 ms 比 0.83%)</strong> を実測。full training run で観測されていた ~10% 分散に対し <strong>約 6x のノイズ削減</strong>。3-regime (iter 1000 / 5000 / final checkpoint、各 n=5) でも σ 1.2-4.6% の範囲に収まり、splat 数が少ない早期 regime ほど相対分散が大きい傾向を確認。有意判定閾値を <code>max(2σ, 1%)</code> と規約化し、以後の gate 判定をこの harness の計測に載せ替える。付随して `--parity` (kernel variant 間の勾配 / binning 一致検証) と `[output] save_ply_at` (checkpoint 保存) を実装、parity mode の実測で production-scale シーンの `sorted_idx` tie-order 非決定性 (~0.2%、真の非決定性であって variant 差ではない) を発見し gate から除外した。
<strong>単発 -48.4% は本 project 最大の 1 施策改善</strong>で、msplat 実測 gap (11m48s vs 3m40s ≈ 3.2×、Lego 30k) を大幅に詰める lever が確定。766.07 → 395.59s は kernel を 1 行も触らず host 側 buffer 管理だけで達成 (bit-exact)。emit_pairs は 38.2% → 1.2% に消滅し、新 bottleneck は backward_raster 31.4% (→ 2-BWD last_contributor の trigger 25% を初超過) と radix_sort 11.7% (GPU compute 本体)。STP (feat.F) は emit の alloc 成分が消えた今、相対効果の再 bench が必要 (Phase 1a の -7.45% は大半が同じ page fault の削減で C0 と重複していた可能性が高い)。教訓: unified memory 環境の profiling では「GPU 時間」に host メモリ管理コストが化ける — per-kernel wallclock だけでなく buffer lifecycle を疑うこと。
別 worktree で実装済みだった C3 (per-tile counting sort) を main の util.rs 分割後の構造 (bench harness commit fe68cfa 由来) に手で移植し統合。smoke compile + unit test 6 本 + 既存 106 test 全 pass、build warning 0。<code>splat bench --parity</code> で数学的正しさを確認 (tile_offsets byte-exact、5 grad buffer tol 1e-4 以内 PASS)。しかし fixed-workload replay (final checkpoint n=10) では <strong>+3.15%</strong> ― 閾値 max(2σ,1%)=4.45% 未満で有意な高速化なし。radix_sort kernel 単体も +7.5% 遅い。12.5k full run の PSNR guard は通過 (-0.036 dB) したが、同じ full run の wallclock は -8.8% と replay の非有意判定に矛盾しており、これは既知の full-run 分散 confound と判断し gate 判定には採用しない (むしろ bench harness の存在意義を裏付ける実例)。default flip は見送り、TileCounting は BackendConfig flag として保持 (正しさは証明済みなので将来 CPU scan を GPU 化する等の改良余地があれば再挑戦可能)。副次効果として sort key <code>(depth_bits<<32)|splat_idx</code> により depth-tie 非決定性を解消した。
1× 工程表 v2 が「AC 復帰後 queue #1」に置いていた counter session を実施し、3 問すべてを実測で閉じた。<strong>(1) busy% 論争は 68〜69% で決着</strong> — bench (final 68.9% / iter5000 67.5%、n=3、cb_dropped=0・overlap 1.00×) と 12.5k full run の補正値 (148.169s busy ÷ 同日 profile=false wallclock 216.12s = 68.6%) が一致。<strong>(2) H1/H2/H3 の verdict は「H1 単独で説明・H2 null・H3 棄却」</strong>。W 比 0.704 ≈ busy 比 0.689 なので activity factor の差 (H2) を持ち出す必要がなく、P-state residency は本実装が P15 に 97.6〜98.0% (bench) 居座る一方、msplat の方が電力上限で P10〜P14 に落ちる — <strong>DVFS で損をしているのは msplat であって本実装ではない</strong>。<strong>(3) 卒論 positive の撤回</strong>: roadmap v2 が期待した「エネルギー 0.7-0.8× = W/PSNR 効率で勝つ」は<strong>不成立</strong>。W が 0.70× でも wallclock が 1.273× 長いので、完走までの GPU energy は <strong>0.897×</strong> (10% 得) に留まり、CPU を含む package energy では <strong>1.062×</strong> (6% 損) に反転する。energy 0.75× を達成するには W 比 0.573× が必要で、実測 0.704× は energy 等価点 (0.764×) の外側。<strong>結論: 卒論 §5 で電力効率を主張軸にはできない。正しい主張は「同じ package 電力枠でより長く回る = 熱設計に優しい」ではなく、単純に『S2/S3 で bubble を潰せば W も energy も改善する余地が 31% 残っている』という engineering debt の定量化。</strong>
<code>BackendConfig</code> 全 16 field を機械走査し、default 以外の variant を全数再判定。実測 9 件のうち <strong>8 件は verdict 維持</strong>、<strong>1 件 (<code>loss_path</code>) が flip</strong>。<code>loss_path = "gpu"</code> は replay final regime <strong>21.210 → 15.591 ms/iter (-26.5%)</strong> / iter5000 <strong>-29.6%</strong>、12.5k full gate (同一 session 交互 A/B、n=3) で <strong>283.00 → 183.00s (-35.3%)</strong>・PSNR <strong>36.142 → 36.188 dB (+0.047、guard ±0.1 内)</strong>。ただし <strong>この flip は公式数値を 1 つも動かさない hygiene</strong> — 全 237 config が <code>loss_path</code> を明示指定済みで 12.5k gate 系は例外なく <code>"gpu"</code>、enum default だけが 2026-04-30 以来実運用から取り残されていた。残り 7 件は validate hard error による構造的非互換 (5) / 禁忌リスト (2) / harness 非対応 (1) / 非 perf variant (3) として理由付きで判定不能を記録。副産物として <code>splat bench</code> の <code>validate()</code> 抜け (無効組合せが exit 0 で silent 別経路実行) を発見・修正した。
<strong>Phase 2 の主戦場が確定</strong>: strategy doc の trigger 3 候補 (separable SSIM / last_contributor / SH-Adam fusion) は全て閾値不発、代わりに <strong>binning 経路 55% の主犯 = per-iter ~1.25GB alloc + Vec 三重往復 (C0)</strong> が最大 lever。C0 (persistent buffer arena、bit-exact、3-4 日) の期待は <strong>wallclock -30〜39% (766→~470s) で単独 gap ≤2.0× 到達圏</strong>。C1 (radix 定数桁 pass skip 16→11、bit-exact、0.5-1 日) が +4-5%。StopThePop は -7.45% で adoption gate (-8%) に僅差未達、default 維持のまま C0 後再判定。5 連敗の教訓「profiling が指す順」が機能した初の事例 — 事前決め打ちなら SSIM (5.2%) に突撃していた。
C0 (-48.4%) に続く Phase 2 第 2 弾で、backward 31.4% の新 bottleneck を kernel 側から -40.3% 削減。<strong>Lego 12.5k = 336.33s で msplat 30K (220s) 比 1.53× まで縮小</strong>し、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% / radix 13.5% / SSIM 7.5% でいずれも trigger 25% 未達 — Phase 2 はここで完了、Phase 3 (再計測 + Pareto v3) へ。
gap sweep の公式 gap 数値を <strong>同日・同一条件の実測で確定</strong>: Lego 12.5k vs msplat 30K の wallclock gap は <strong>2.10×</strong> (352.3s vs 167.7s、両者 profiling なし) — Phase 2 の 1.53× は spike の古い msplat 値 (219.8s) 起因の過小評価だった。一方 <strong>matched-wallclock 断面 (本実装 7.5k = 181.4s、msplat の 1.08×)</strong> では brush convention の同一 evaluator cross-eval で本実装が <strong>+0.94 dB</strong> (35.41 vs 34.47)。PSNR 比較は eval convention に強く依存し (white-bg では msplat +1.09 dB)、p1-a-3 の「訓練/評価 convention coupling」を第三者実装との比較で再実証した。msplat の native 品質が spike 比 +1.05 dB 向上した主因は今回の対称条件 (同一 culled init.ply 5207 pts・train 100 view 全量・常時フル解像度) にあり、msplat 側の条件を今回初めて本実装と揃えた結果。卒論 §5 の direct comparison 表はこの数値で置き換える。
別 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 は <strong>final regime -22.9% / iter5000 -21.9%</strong> と 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 化。
1× 工程表 v2 の並列性能軸で<strong>本命に格上げ</strong>されていた S2 を gate し、採用した。W2 が backward/loss chain を 1 CB に畳んだのに対し S2 は forward 側を畳む — radix の per-pass CPU prefix scan を hierarchical GPU scan (bit-exact な整数 prefix sum) に、pair_count の host readback を indirect dispatch に置き換え、forward 全段を <strong>1 CB / 1 encoder / 末尾 1 wait</strong> に連結した。replay <strong>final -12.3% / iter5000 -13.3%</strong> (閾値 1.0〜1.8% の 8〜13 倍)、12.5k full run は<strong>同一 session 交互 A/B (ABBAAB) n=3 で 208.26 → 187.65s = -9.9%</strong>。<strong>counter session が積み残した「busy 68.9%」は 79.8% まで回復</strong>し、sync-tax は 5.21 → 2.86 ms/iter (-45%)。roadmap が注目トレードに挙げた「dispatch 26 → ~60 の overhead」は <strong>busy ms/iter +0.20 = 回収額の 1/11〜1/24</strong> と定量的にケリがつき、follow-up (radix reduce の histogram fold) は<strong>総額 -1.1% 未満と判明したため S3 の後ろに defer</strong>。<strong>full run の Δ (-9.9%) が replay の Δ (-12.3%) を下回る一方、iteration 別に見ると -24.7% (iter1000) → -10.0% (iter12500) と単調に縮む</strong> — S2 が削るのが<strong>splat 数に依らない固定の per-iter host コスト</strong>であることの直接証拠で、W1/W2 (GPU 仕事量に比例する施策) とは pass-through の性質が異なる。msplat 同日等価 gap は <strong>1.273× → 1.105×</strong>。累計 (数学的同値の施策のみ) 766.07 → 187.65s = <strong>-75.5%</strong>。
1× 工程表 v2 の第 1 波。msplat / Inria / brush の 3 実装が持ち本実装だけ欠落していた backward の 2 つの skip を、bit-exact の等価性論証つきで移植した。backward_raster は LC (2-BWD) 後の 7.2ms/call から 4.65ms/call へ -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%) / radix (15.0%) で、W2 (encoder/CB 統合) と計測 (counter session) が次段。
1× 工程表 v2 の第 2 波。HW 4 軸調査 #2 の CB/wait 監査 (本実装 ~21 CB / ~11 wait vs msplat 1 CB / 0 wait) を受け、submission 戦略を BackendConfig の enum variant として実装・gate した。同一 CB 内の連続 encoder は firmware が CPU 介在なしに back-to-back 実行するため、per-kernel の commit + waitUntilCompleted (0.1〜1 ms 級の full round trip) が丸ごと消える。replay 全体で -13.7% (final)、12.5k full run は 241.41 → 219.51s で msplat 同日等価 gap は 1.44× → 1.31× に縮小。累計 (数学的同値の施策のみ) は 766.07 → 219.51s = -71.3%。expected gate 帯 -5〜15% (F.3 overlap 割引済) のほぼ上限で着弾し、F.3 (radix GPU scan) が単独敗北した『wait 除去』が、chain 全体の統合では大きく勝つことを示した — 部分 wait 除去と全 chain 統合の ROI 差は axis 3 (unified memory / submission 論) の narrative 素材。次の律速は forward 30% (radix 18% 内数) / chain GPU 26%。
<strong>bicycle baseline (Phase I recipe 流用) = 15.549 dB / Kerbl 2023 比 -9.7 dB</strong>、tuned (refine.stop_iter=25000, capacity=3M、2 変数のみ isolated tuning) = <strong>15.603 dB / Δ +0.054 dB (実質 noise 圏)</strong>。splats +55% (311k→483k) を追加しても PSNR は動かず、wallclock も ±0。<strong>bottleneck は refine schedule / capacity growth ではなく、より深い layer</strong> (opacity reset cadence / grad threshold / unbounded outdoor scene handling)。<strong>Case (b) scope-out 確定</strong>: Apple Silicon native 実装の scope 境界は synthetic + object-centric に留まり、Mip-NeRF 360 実写は refine + capacity 調整では回収不能、future work として **本質的な refine schedule 再設計** or **msplat / MCMC 系の densification 経路の再挑戦**が必要。<strong>本 finding は §5.4 の MCMC 5 連敗 pattern と完全に一貫</strong> (measurement で scope 境界を数値化、fix cost を明示化)。
<strong>G3 MCMC fix3 = 5 連敗確定</strong>。fix2 (17.38 dB) 敗因の calibration ズレを、既実装の 3 欠陥修正版で再挑戦。<strong>500 iter smoke で crash なし完走</strong>、<strong>2000 iter で 10-12 dB 頭打ち</strong>、<strong>ablation で scale_eigen_l1 の毒性を -4.4 dB と測定</strong>、<strong>scale_l1 除去した relocation + growth schedule の 30k full 2 パターンで PSNR 14.65 / 14.69 dB</strong> (Phase I baseline 36.11 dB 比 -21 dB)。犯人は複合: (1) scale_eigen_l1 実装が過剰罰化 or 符号ミス、(2) relocation の Eq.9 probability-preserving 実装が本実装の SoA parameterization と結合していない (splats 1.3-1.8M まで肥大化するが PSNR が付いてこない)。<strong>7 月実行プラン G3 の timebox 判定基準通り即撤退</strong>、卒論 §5.4 negative finding として 5 連敗目に確定、future work 送り。<strong>ただし本 negative finding は従来の 4 連敗より格段に強い evidence</strong> (component ablation で犯人を数値で切り分け、30k full の decisive failure まで到達)、卒論 measurement contribution として §5.4 で厚く記述可能。
<strong>msplat (rayanht) v1.1.3 を M4 Max で実測完了</strong>。Lego 30K で 219.8s (3m40s) / 35.48 dB / 208k splats、chair 7K で 17.58s / 33.81 dB を確認。<strong>本実装 Phase H lego (11m48s / 36.26 dB) に対し msplat は wallclock 3.2× 高速、ただし PSNR は -0.78 dB</strong>。materials 7K では PSNR 8.80 / splats 367 と densification が壊れた — msplat の scene robustness 弱点が判明し、本実装の <strong>universal な density 動作</strong>が明確な差別化軸として確定。<strong>本実装 Phase I 8 scene のうち 5 scene が msplat lego 30K の 35.48 dB を上回る</strong> (Lego 36.26 / chair 35.88 / hotdog 37.37 / mic 36.62 / drums は 27 のみ)。Pareto plot で msplat は左上 (速い + 中品質)、本実装は右側 (遅い + 高品質 + 全 scene robust) と vector が直交。本 spike により <strong>A (Reframing narrative) の killer figure が確定</strong>、<strong>B (G.2 backport) は引き続き NO-GO</strong> (msplat が既に kernel fusion + pre-allocated bins まで実装済、本実装が追いつく工数は大)、<strong>E (msplat 著者接触) の materials bug 報告は良い PR ネタ</strong>。
Phase G (速度改善 loop) で 4 candidate × 8 scene の Pareto landscape 確定。<strong>結論</strong>: **G.3 alone 30k = universal quality improvement** (8 scene mean **33.592 dB**、Phase D 33.485 比 **+0.107 dB**、7/8 scene で win、wallclock +10.2%、splats +29%)、特に **mic は stacked で -6.05 dB だったが G.3 alone なら +0.244 dB 救済**。<strong>G.1 stop15k</strong> は dense scene で acceptable (Lego/chair/hotdog で Phase D 比 -0.5 dB 圏内) も sparse scene で大幅劣化 (mic -5.84/ficus -1.79)、8 scene mean -1.39 dB で Pareto worse、brush parity (32.86) を -0.76 dB 下回り。<strong>G.1+G.3 stacked</strong> は Lego-specific Pareto sweet spot (16m13s / 36.254 dB / +0.15 dB) だが multi-scene mean 31.998 dB で stacked < G.1 alone、SH warmup の効果が early stop で truncate されて sparse scene で逆効果 (ficus -3.15、mic -6.05)。<strong>G.2 audit</strong> は 4.7× gap が architectural dispatch (Burn/CubeCL 内部 batching vs Metal 直 per-kernel sync) と判明、Phase F 5 連続 falsification への統一的説明、kernel/algorithm 軸では覆せない構造的 finding。<strong>axis 1 future work ROI 階層</strong>: <strong>algorithmic compute reduction > architectural dispatch > kernel-level micro-opt</strong>。Phase G が axis 1 「Apple Silicon native 最適化の ROI 階層」を構造的に確定、卒論 §5.4 narrative の集大成。
Phase G で G.3 alone 30k = universal Pareto improvement (+0.107 dB / +10% wall) を確定した後、**Lego の (wallclock, PSNR) Pareto curve を stop_iter × 6 点 で精密 map**。<strong>結果</strong>: stop_iter=10000 は brush (9m08s / 32.04 dB) を完全 Pareto-dominate (8m42s / 35.931 dB = **同時間で +3.89 dB**)、stop_iter=12500 は Phase D 30k (41m54s / 36.106 dB) を Pareto-dominate (11m48s / 36.259 dB = **-71% wallclock + 0.15 dB**)、stop_iter=17500 以降は marginal +0.1 dB のみで diminishing returns 顕著。<strong>anomaly</strong>: stop_iter=25000 が 36.092 dB と 20000 (36.359) より -0.27 dB 低い (variance or training instability の可能性)。<strong>Scene-validation</strong>: ficus @ stop_iter=12500 = **30.103 dB** (Phase D 34.22 比 -4.12 dB の大幅 fail)、**Lego sweet spot が scene-dependent と確定**。mic / drums / hotdog / ship 等 sparse scene でも同様の fail が予想され (G.1 stacked パターンと整合)、universal config では Phase G.3 alone 30k が依然 best。<strong>Phase H の最終 framing</strong>: Lego の Pareto curve は dense texture scene 固有、sparse scene は full SH from start (no sh_progressive) または full 30k iter が必要。<strong>axis 1 future work</strong>: scene-adaptive iter budget (Lego/chair/materials @ 12500、ficus/drums/mic 等 @ 30000) で 8 scene mean を維持しつつ total wallclock を 5h 36m → ~3h に -40-50% 削減可能と推定。
Phase H で Lego stop_iter=12500 が Pareto sweet spot だが ficus/mic で大幅 fail (-4.12 / -6.03 dB) と scene-dependent 確定後、**Phase I で chair / materials @ stop_iter=12500 も fast converger と確認** (G.3 30k 比 -0.05〜-0.07 dB のみで essentially same)。これにより <strong>scene-adaptive iter budget</strong> (Lego/chair/materials @ 12500、ficus/drums/hotdog/mic/ship @ 30000) を構成、<strong>既存 8 scene 全データ点が揃った状態で 8 scene mean を算出</strong>。<strong>結果</strong>: scene-adaptive 8 scene mean **33.561 dB** / total wallclock **3h 50m 10s**、Phase D 30k 比 <strong>+0.077 dB / -24.4% wallclock</strong>、G.3 30k 比 <strong>-0.031 dB (within noise) / -31.6% wallclock</strong>、brush 比 <strong>+0.701 dB</strong>。<strong>Pareto front の両軸で improvement</strong>: Phase D を quality + speed 両方で dominate、G.3 30k quality を 1/3 短時間で達成。**axis 1 contribution の最終形**: kernel-level 直叩きではなく <strong>scene-adaptive iter budget + sh_progressive + opacity_decay の組み合わせ</strong>が Apple Silicon native Metal 最適化の universal Pareto improvement。卒論 §5.4.7 末尾 + §6 future work で本 Phase I を明示、scene-adaptive を新 universal default として推奨。
User task brief は Phase D 375k 文脈で旧 A.6 (~1% wallclock ROI) を再評価し f16 packed の真の bandwidth ROI を引き出すことを期待したが、orientation 段階で feat.G 実装の事実関係を確認した結果、3 つの factual error (32 byte / -11% / ~12 MB) が判明。bound math (rasterize fwd+bwd share 上限 30% × bandwidth 削減 11%) より wallclock 上限 ~3.3%、user brief の 20-40% 期待は実装の物理特性と整合しない。加えて M5 Lego val gate margin (+0.11 dB) より RGB f16 round-trip 誤差 (rel 5e-4、abs ~0.5 dB drift 想定) の方が大きい可能性、再着手は M5 gate を割るリスク。orientation 段階で halt、bench 不実施。
5 kernel (clean baseline share 合計 55.1%) を Explore subagent で構造的 audit、Apple Silicon 特化最適化候補を kernel 単位で 2-4 個ずつ抽出。<strong>最大の発見</strong>: **emit_pairs_simd PSO は既に実装済**、<code>use_simd_emit: Cell::new(false)</code> で gate off、comment に「30k validation 後 default true 化予定」(tile_bin.rs:86-87)、**Phase D 30k 完遂で即 flip 可能** (-0.7-1.0% wallclock 即時、zero risk)。同様の即 actionable 機会: f16 forward kernel <code>render_splats_f16</code> は env <code>SPLAT_F16_FORWARD=1</code> gate (現在 disabled、A/B test 必須 PSNR risk MED-HIGH)。<strong>Tier 2 (Phase E scope)</strong>: radix_sort GPU prefix sum (-0.54-0.82% wallclock、CPU-GPU 16-pass sync 除去)、backward_raster imageblock+TBDR (-0.67-1.07% wallclock、tile-local 累積で atomic 大幅削減)。<strong>累計 -1.5-2.5% wallclock 改善余地確定、卒論 §6 future work 候補と pilot 実装目標</strong>。backward SIMD reduction は既に default 有効 (rasterize.rs:642、2.43× win 享受中で確認済)、SSIM は eval-only で training 直接寄与なしのため Tier 3。
audit (p1-axis1-metal-opt-audit) で Tier 1「即 actionable gate flip、-0.7-1.0% wallclock、zero risk」と分類した 2 候補を Lego 5k smoke A/B で実証検証。<strong>emit_pairs_simd は total wallclock +4.7% の net regression</strong> (112.11s → 117.38s、~10 kernel 平均なので noise floor 小、real regression 確定)、ただし per-kernel emit_pairs 単体は +8.5% で baseline 2 sample 変動 (4.814 / 5.129、6.5%) と近い hedge 必要。<strong>f16 forward は ~+2.5% wallclock</strong> (114.97s)、run-to-run variance 圏内で improvement / regression いずれも明確に検出できず。<strong>PSNR は両者で許容範囲</strong> (emit_simd -0.132 dB、f16 +0.075 dB、atomic order / fp 順序由来想定)。**audit の予測 calibration data**: Tier 1 SIMD-reduction 系の効果は theory より小さく overhead が打ち消し、Tier 2 別 mechanism (CPU-GPU sync 除去) は別途検証必要、Tier 2 同 family (backward TBDR) は falsification 拡大適用で skip 判断強化。卒論 narrative 価値: 「audit theoretical predictions vs empirical measurements」の方法論 paragraph を §5.4 negative findings 章 (chapter-5-4-negative-findings.md) に追加候補。
audit (p1-axis1-metal-opt-audit) で Tier 2 「radix_sort GPU prefix sum、-0.5-0.8% wallclock、LOW PSNR risk」と分類した候補を empirical 検証。<strong>bit-exact 実装は完成</strong> (16-thread single-threadgroup kernel、Apple SIMD prefix exclusive sum + per-digit serial scan、100k random / 500k packed keys / edge cases 6 種で CPU stable sort と byte-for-byte 一致)、しかし 5k Lego smoke で <strong>wallclock 115.83s → 124.41s (+7.4%)、ts_fwd_radix_sort 4.768 → 6.733 ms/call (+41%)</strong> の net regression。sanity re-run (118.73s / 6.402ms) で再現確認、run-to-run 変動の上。<strong>PSNR は parity</strong> (31.604 → 31.635 dB、bit-exact 経路で 0 drift 期待、観測 +0.03 dB は session noise)。<strong>Likely mechanism</strong>: StorageModeShared buffer での back-to-back compute encoder 間で Metal が implicit fence を挿入 (hist→scan の buf_hist、scan→scatter の buf_offsets で read-after-write hazard)、TBDR pipeline stall。旧 CPU 経路は buf_hist→buf_offsets 変換を host で実行するため GPU 内 memory dependency が無く、<strong>「除去した wait_until_completed」は実は CPU prefix scan と overlap していた active work</strong> だった。教訓: 「CPU 介在を on-GPU に置換」族の audit 予測は overlap の存在を見落とすため systematically overestimate、Tier 2 同 family (backward TBDR、tile-local accumulator) の skip 判断強化。kernel + tests は env <code>SPLAT_RADIX_GPU_SCAN=1</code> で opt-in (future workload hedge)。
Explore subagent (Sonnet very thorough) で brush 18ms/iter vs splat-rs 84ms/iter (4.67×) の真因を architectural 差で構造特定。<strong>brush は Burn/CubeCL backend の <code>launch_unchecked()</code> async dispatch + 内部 command buffer batching</strong> で per-iter 5-7 explicit awaits → ~5 actual GPU flushes。一方 <strong>splat-rs は per kernel 毎に <code>cmd.wait_until_completed()</code> で 10-50 GPU flushes</strong>。計算: 17ms GPU compute + ~25ms wait overhead (~2.5ms/wait × ~10) = ~42ms、実測 84ms とは ~2× ずれあるが (subagent quantification の不確実性)、order-of-magnitude は一致。<strong>これは Phase F 5 連続 falsification への統一的構造説明</strong>: kernel-level micro-opt (SIMD reduction / f16 accumulator / radix GPU prefix / TBDR imageblock 等) が効かなかったのは bottleneck が <strong>per-kernel compute ではなく dispatch synchronization architecture</strong> だったから。**主仮説 ranking** (subagent assessment): (1) command buffer batching (50% of gap、移植 VERY HIGH cost 6-10 週)、(2) async readback (15%、MEDIUM cost 1-2 週、+3-5% expected)、(3) kernel fusion (5-10%、EXTREME cost)。**ただし subagent quantification は overestimate 傾向あり** (Phase F.3 で「removed wait was overlapping with CPU work, not idle」発覚と矛盾、wait は free な場合もある)。卒論 narrative としては <strong>structural explanation</strong> として極めて価値高い、§5.4 negative findings 章で「Phase F 全 kernel-level 改善試行は architectural mismatch だった」統一的 paragraph 候補。
Phase G compute reduction family の G.3 (SH-progressive growth) を実装 + bit-exact unit tests (11 件、cargo test 43 件 全 pass) + **3 layer の Lego 結果検証**。<strong>(1) 5k smoke</strong>: wallclock -13.9% / splats -22% / PSNR -0.12 dB、cascading splat reduction を観測。<strong>(2) 30k full validation</strong>: wallclock **-1.9%** (5k から大幅縮小)、splats **+30%** (5k から逆転)、PSNR **+0.28 dB** (quality improvement!)。5k smoke の cascading 効果は refine.stop_iter=1500 による artifact、30k では sh unlock 完了 (iter 3000) 後に refine が iter 15000 まで full SH で継続 → splats baseline より grow。<strong>(3) G.1+G.3 stacked (max_steps=15000 + sh_progressive)</strong>: Lego **16m13s / 36.254 dB / 428k splats** = Phase D 比 **-61% wallclock + 0.15 dB PSNR** で <strong>Pareto sweet spot</strong> 確定。<strong>Key reframe</strong>: G.3 は「speed win」ではなく「**quality improvement at no speed cost**」、stacked variant で G.1 speed と SH warmup quality gain を統合。<strong>Implementation</strong>: <code>[trainer.sh_progressive]</code> section (default disabled、全 backward compat)、<code>CameraGpu</code> struct を <code>sh_degree</code> (buffer layout) と <code>active_sh_degree</code> (per-iter eval) に分離。<strong>Calibration data point</strong>: Phase F 5 連続 falsification + G.3 5k smoke artifact = audit / smoke overestimate 6 例目、「smoke は production scale を representative しない」が新教訓。8 scene chain validation pending。<strong>卒論 narrative</strong>: Phase F (kernel-level fail) → G.2 (architectural insight) → G.3 (algorithmic reframe: speed → quality + stacked Pareto) の 3 family 比較で「Apple Silicon native 最適化は <strong>algorithmic compute reduction + early stop の組み合わせが Pareto-optimal</strong>」という構造的 calibration。
Per-iter target upload kernel を完全除去 (5000 calls → 0)、構造的には kernel 一つ消えた成果。 だが wallclock ROI は **予想 -5.5% に対し実測 -0.23%** (-1/25)、profile baseline の "5.6% share" は GPU contention 3x 環境での host stall 値で、平常 contention では host upload は既に GPU 計算と overlap していた。 PSNR は seed 同一でも +0.14 dB drift (Metal driver の buffer 配置順序差 → atomic ordering 差 → refine.split RNG 経由)、5k smoke の noise floor 内。 実装は trivial (train_loop entry で `Vec<Buffer>` 構築、train_step に `Option<&Buffer>` 追加)、commit 残しておく価値はあるが、roadmap 上の位置付けは "deprioritize / cleanup level" に修正。 **真の優先順位は radix_sort 改善 (27% share) と A.7 ICB batching tail に集中すべき**。
Phase D opacity_decay (rate=0.004 brush default) を 7 scene × 30k full chain bench、Lego val Phase D 30k と合わせて 8 scene 集計。**全 scene で baseline brushcompat 30k 比 PSNR + splats + wallclock すべて改善 (universal win-win-win)**: PSNR +0.18〜+1.42 dB / splats -57〜-78% / wallclock -39〜-69%。8 scene mean 33.49 dB vs brush paper 8 scene mean 32.86 dB = **+0.63 dB 上回り**、本実装が brush の multi-scene mean を decisive に超えた。brush 超え 3 scene (Lego val +4.07 / drums +1.05 / mic +1.02)、4 scene が brush 比 ±0.7 dB 圏内 (chair -0.02 / hotdog -0.39 / ship -0.01 / materials -0.10)、最遠 scene でも ficus -0.65 で接近。全体 wallclock baseline chain (13h+) → Phase D re-chain 5h 5m (-61%)、mean splats 1.4M → 428k (-69%) で brush 282k に肉薄。P1.M5 完全達成 (Lego val > 36 dB ✅ + multi-scene mean > 32 dB ✅)、卒論 central evaluation table の final 数字確定、universal claim 完全実証。
opacity_decay_rate を 5 点 (0.001/0.002/0.004 default/0.006/0.008) で 5k smoke sweep。**rate=0.002 で PSNR 32.090 dB (default +0.40 dB)** と最高、splats は 88k で +5.8% 微増。rate を上げる (0.006-0.008) と splats は 80k 帯に削減されるが PSNR 影響は 5k variance σ ±0.32 dB 内。Phase D 30k baseline (rate=0.004) は既に M5 +0.11 突破済 (36.106 dB)、rate 変更の追加 +0.2-0.5 dB は smoke noise と並ぶ ROI 不明確。multi-scene Phase D re-chain も brush 互換性維持の観点で rate=0.004 維持を推奨。
Lego brushcompat + opacity decay 30k で training-time eval 36.106 dB (val 100 view, brush convention, raw)、independent eval 36.163 dB (brush q8)。baseline 30k (35.184 dB) を **+0.92 dB 上回り**、splats を 846,689 → 375,146 に **-55.6% 削減**、wallclock を 1h 02m → 41m 54s に **-32% 短縮**。これは trade-off と想定していた PSNR/splats/wallclock が **完全 win-win-win** に。M5 個別 scene gate (Lego brush conv > 36 dB) を val で達成、brush 自身 val 32.038 dB を +4.07 dB 上回り、本実装が brush を decisive に超えた。test subset (n=36) も +0.75 dB 改善 (33.315 → 34.065)、brush paper test 37.40 との gap を -3.34 dB まで縮小。Stage 1 smoke 推定 (splats -11.6%) を 30k で -56% に拡大、opacity decay の効果は iter 累積で増大することを実証。次 step は multi-scene Phase D 7 scene re-chain (chain 完了後 schedule)、低 wallclock + 低 splats での M5 multi-scene parity 完遂を狙う。
Phase D 30k 実測 wallclock 41m54s vs brush 9m08s = -4.6x gap の原因について、task は `splat process CPU 63.4% = 1 core only` → 「refine の host RMW loop が CPU 1-thread bound」と仮説立てた。本 Phase E ではこの仮説を SPLAT_TIMING profile で実測。5k smoke (84k splats、p1-e-profile-5k.toml) の kernel breakdown: **ts_forward 60.1% (123s) / ts_loss_gpu 28.0% (57s) / ts_adam 4.8% (9.9s) / ts_target_upload 3.9% (8.1s) / ts_project_back 2.3% (4.75s) / ts_refine_compact 0.6% (1.14s, 103ms/call × 11) / ts_refine_accumulate 0.3% (605ms) / ts_opacity_decay 0.0046% (957µs)**。**refine 全体で <1%** = refine を完璧に GPU 化しても全体 wallclock は -1% も短縮されない。代わりに demo kernel として `refine_opacity_decay.metal` を実装し、kernel + Rust pipeline + `refine.gpu_path` flag plumbing pattern を validate (CPU vs GPU max diff 1.5e-5、5k full PSNR delta -0.21 dB = 許容内)。Phase F の真の target は (a) forward subdivision で判明した tile-binning chain (`ts_fwd_sort 15.5% + ts_fwd_emit 12.8%`)、(b) Adam の 5x sequential `cmd.wait_until_completed` (1 cmd buffer 化で ~5% 削減期待)、(c) target_upload preload (~4% 削減期待) の 3 つ。
Phase D Lego brushcompat 30k で wallclock 42m / brush 9m gap (-4.6x) の真の bottleneck を per-kernel host Instant 計測で数値化。**仮説 (refine host RMW dominant) は棄却**、refine は 2.6% に過ぎず Phase E GPU 化の ROI は ~3% (期待していた -25% の 1/8)。実 dominant は radix_sort 27% / ssim 16% / backward 14%。優先順位を **target_upload キャッシュ (即時 -5.6%) → radix_sort 改善 (-10〜15% 期待) → A.7 ICB batching tail (-5% 期待) → Phase E は卒論後** に反転すべき。
clean single-process で per-kernel share を取り直し、前 profile baseline (multi-process contention 中) と比較すると <strong>share が大幅 shift</strong>: ts_fwd_radix_sort 27.0% → **13.6%** (-13.4 pt)、ts_fwd_emit_pairs 6.5% → **14.2%** (+7.7 pt)、ts_forward 全体 60.1% → **36.7%** (-23.4 pt)。これは前 profile の share が contention で over-state されていた決定的証拠 (target_upload subagent の share 5.6% → 実 ROI 0.23% を kernel level で再現)。新 axis 1 ROI 上限: emit_pairs 改善 -14% / radix_sort -13% / backward_raster -13% / ssim_fusion -7-8%。Phase E (refine GPU 化) の ROI 仮説 -5x は元々 share 2.6% で 1/40 過大評価だったが、本 clean baseline でも refine 0.2% に縮小、棄却強化。target_upload は本 clean baseline で完全消滅 (cache 化済)。
8 シーン complete (lego + 7 新規) 30k 完遂。シーン依存性が PSNR で 17.6 dB の幅 (materials 12.71 〜 hotdog 30.29)、mean 18.95 ± 6.0 dB。本実装の brush SoTA 比 gap は scene-dependent で -7.4 dB (hotdog) 〜 -22.3 dB (ficus 含む)。共通要因仮説: SfM init.ply の sparsity (細い枝 / マイク / 反射 PBR で薄い) + refine grad_threshold の lego/hotdog tuning over-fit。卒論 evaluation で「lego baseline + multi-scene mean ± std」併記必須。
brush eval は (1) AlphaMode::Transparent で GT を α premultiply、(2) bg=Vec3::ZERO の黒背景に render、(3) composite_bg=None で premultiplied 同士を直接比較、(4) 8-bit roundtrip 後に MSE = mean((pred−gt)²) over H·W·3、(5) PSNR = 10·log10(1/MSE)。これは NeRF Synthetic (RGBA で α=0 の透明領域が支配的) において **透明領域は pred=gt=0 で完全一致** となり、MSE 分母に 0 寄与が大量に入る → conventional 「白背景に composite してから PSNR」より高く出る。splat-rs 側の eval 規約を A.2 で確認し、A.3 で「同 convention 下での真の gap」を測定する必要あり。
splat-rs trainer の eval は (1) val split 100 view・brush は test split 200 view、(2) PSNR は RGB のみ・α 除外、(3) rendered は raw f32 (clamp / quantize なし)・brush 標準は u8 quant 後、(4) rendered は bg 合成なしで Σαi·Ti·ci のみ・target は white-bg pre-composite — の 4 つの diff 軸を持つ。training loss は 4ch (α 含む) で動くため、α 通り collapse が暗黙の white-bg 効果を作るが、convergence は不完全。P1.A.3 で 7 項目の切り分け reproducer を作り apparent gap (推定 −3〜−6 dB) を分離する。
splat-rs `final.ply` (24.879 dB legacy/val baseline) を brush 準拠 convention (premultiplied GT + bg=ZERO 比較 + 8-bit roundtrip) で再評価すると **1.67 dB に崩壊**。audit §6 が予測した +3〜+5 dB 底上げと逆方向に -23 dB。原因は trainer が white-bg target で学習されており、背景領域を opaque-white splat で埋めるよう収束した結果、brush 流の bg=ZERO 比較では背景 pixel 全体で MSE≈1 が systematic に乗る。`view_00.png` 目視確認 (背景は白い不透明領域) で機構を確定。**training と eval の convention は coupling しており、eval pipeline だけ揃える apparent-gap 仮説は不成立**。卒研 P1.M2/M3 に向けては「training loss も brush 化 (RGBA 4ch L1 を α=0 領域で背景に penalty を吹かさない構造)」が必須要件。8-bit quantize 単体の impact はほぼ無視可能 (legacy 24.879 → 24.879、brush 1.605 → 1.667、+0.06 dB)。
両 trainer の eval pipeline を file:line で完全 audit、PSNR formula 本体 (MAX=1 / log10 / RGB only / per-view mean) は同等だが、(1) test split (200 view) vs val split (100 view)、(2) background composite convention の **完全逆方向**、(3) 8-bit roundtrip 有無、(4) α-mask 経路、(5) clamp/quantize 等 7 軸で diff を確認。最大の発見は brush の premultiplied-α + bg=ZERO eval が NeRF Synthetic の透明領域で構造的に PSNR を +3 dB 以上嵩上げする一方、splat-rs は target に white pre-composite / rendered に bg 合成なしの mismatch で convergence 残差が MSE に直接残る。apparent gap の推定 -3〜-6 dB を A.3 reproducer で実証予定、残り -6〜-9 dB が真の algorithmic gap。
Lego sh3 30k で gt_convention=premultiplied (brush 互換) を立てると、4-way eval で legacy=1.60 / brush=35.24 dB。**brush 自身 val 32.0 dB を +3.20 dB 上回る** 結果。M3 lifeline (30 dB) を +5.24 dB 突破、M5 (36 dB) まで -0.76 dB に到達。Phase A 主仮説 (apparent gap -3〜-6 dB) は falsify されたが、coupling 解消の真の効果は **+33.6 dB shift (1.67 → 35.24)**、想定 (+10 dB) の 3 倍。実装は configs 1 行 (gt_convention) + dataset.rs (load_rgba_premultiplied path 追加、既に Stage 1 で merge 済) のみ、既存 30k legacy bench との apples-to-apples comparison が可能。brush の wallclock 38% 高速化は 30k でも継続 (splats 1M-cap で 846k 到達、refine が攻撃的 split)、ただし brush 自身 282k に比べて 3 倍、本実装が capacity を未活用 (refine を絞る余地あり、Phase D で検証可能)。次 Step は multi-scene 8 シーン展開で universal claim 確定、brush mean 33.32 dB 超えで multi-scene parity 完全達成を狙う。
P1.A.3 で `splat-rs trainer が white-bg target で学習 → 背景を opaque-white splat で埋める → brush 流 eval (bg=ZERO 比較) で MSE≈1 崩壊` と診断された coupling を、**GT loader を premultiplied 経路に切替えるだけ** で解消できるか 5k smoke で検証。同一 hyperparameter (`2026-05-22-2155-lego-sh3-30k.toml` の iter のみ 5k 短縮) で `data.gt_convention=white_bg` vs `data.gt_convention=premultiplied` を独立 training し、各 final.ply を 2 通り convention で eval (4 cell)。結果: brush trainer × brush eval = **31.334 dB**、legacy trainer × brush eval = 1.628 dB と完全に対比、coupling が双方向に存在することも symmetry test (brush trainer × legacy eval = 1.595 dB) で確定。5k 段階で既に B-N 30k baseline (24.88 dB legacy) を **brush eval 系で +6.5 dB 超え**、brush 公称 37 dB との gap は -5.7 dB のみ。Stage 1 hypothesis (10+ dB) を 21 dB 上回り、coupling 解消が brush parity への critical path であることを定量実証。実装は `splat-cli/src/config.rs` に `data.gt_convention: GtConvention` enum 追加 (default=`WhiteBg`、既存 configs 完全互換) + `train.rs` の train/val load を `load_nerf_synthetic_with_convention` に切替、合計 4 file の最小差分。loss kernel (`loss.metal:31-88`) は変更不要 (n_total=W·H·4 が α channel を含み、premultiplied target の α=0 領域が `rendered α (=1-T) → 0` の natural pressure を提供、brush の match_alpha 機構と同等効果)。
brush の `refine_splats()` (train.rs:611-619) と同じ sigmoid-space formula で opacity decay を refine cadence に統合: `new_opac = sigmoid(raw) - rate*(1-train_t)` → `clamp(1e-12, 1-1e-12)` → `inv_sigmoid`。5k Lego smoke で PSNR は維持以上 (31.31 → 31.69 dB、+0.38 dB)、splats は **-11.6%** 削減 (93,948 → 83,093)、wallclock は +23% (1500 iter で全 splat 触る host loop が支配的、N=83k で問題ない範囲)。これにより 30k に進めば brush 282k 帯 (Stage 2 の 846k からの大幅削減) + PSNR ≥ 34 dB の同時達成が射程に入る。axis 1 (native Metal) ではなく axis 3 (unified memory CPU RMW) を活用した実装で、refine 周辺の O(N)/refine_every オペレーションには合理的選択 (Metal dispatch overhead > 実 work)。
Lego brushcompat 30k final.ply を test split subset (n=36/200、ローカルに残っている RGB のみ) で eval すると 33.315 dB (q8) / 33.241 dB (raw)。val 100 view 35.237 dB (q8) との Δ = -1.92 dB は novel view (test) vs near-train view (val) の generalization gap (brush 自身も val 32.038 → test 37.40 と +5.36 dB 上振れする方向なので、本実装は test で逆に -1.9 dB 劣化、合計の apples-to-apples diff は -4 〜 -5 dB)。brush paper 37.40 dB との差は -4.09 dB で、val ベースで主張していた `brush 超え` claim は test split に拡張すると **不成立**。n=36 (18% subset) の random subsampling bias は mean PSNR で ±1〜2 dB 程度と見積もれるが、4 dB の gap を埋めるには足りない。本 finding により P1 計画の最終判定は `val split で brush parity + α 達成、test split (novel view generalization) では brush に未達` という mixed 結果で確定。実装側のアウトプットとして `splat eval --split-file <PATH>` flag が追加され、任意 transforms JSON での eval が可能になった (subset / 外部 split 互換)。
TBDR imageblock_data ベースの SSIM tile shader 化は render pipeline 大改修 + backward 設計 + 既存テスト 23 件への影響が大きく、卒論 time-box では見合わない。必要要件のみ記録して close。期待効果は SSIM kernel -50% / trainer 全体 -3〜5%。
Neumaier compensated summation の compensator term は MSL compiler の algebraic optimization で消去され、loss は bit-identical。Kahan は wallclock overhead だけ残し variance reduction 効果ゼロ。
M-3.x lego sh3 30k の PSNR variance は σ ±0.32 dB / range 0.885 dB (4 run estimate)、wallclock variance は σ ±2.4% / range 5.2%。原因は SIMD backward kernel の atomic_fetch_add 順序非決定性で、A.10 Kahan で消えない (compensator も bit-identical のところ)。卒論 finding として「Apple Silicon の variance band は数値精度の問題でなく GPU scheduler 由来」と確定。
T&T を取り込むには dataset DL 5-10GB + COLMAP SfM + trainer 入力 format 対応 + eval indicator 再設計 + long run × 数シーンが必要で 2-3 日コース。NeRF Synthetic 8 シーン整備で幅出しは達成済みのため close。
Splat2DPacked kernel pair は完成 (cargo test 73/73 pass) だが、trainer forward path は fp32 path のみで packed kernel を呼ぶ route がない。理論上 -39% memory traffic / splat だが kernel pair 単独 bench で wallclock 効果 ~1% と既知。close。
forward / backward の各 chain を 1 cmd buffer に集約する simpler batching plan。期待効果 +15-30% wallclock 改善 (commit overhead 20-50% を集約)。スタイル A (Option<&CommandBuffer> opt-in) で既存テスト 23 件を touch せず実装。target -10% wallclock / PSNR drift < 0.05 dB。
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 が予想より小さい示唆。
A.7 batched cmd buffer の wallclock 改善は scene 依存で chair -18.6% / hotdog -5.4% / drums -3.4% / ficus -1.6% / lego -6.16% の 5 シーン (12x の幅)。chair の突出は splat 数最大 (~130k) + scene geometry の compute/commit ratio が高いことが要因と推測。一方 ficus / drums は variance 範囲内、独立 effect 断定不可。卒論で「A.7 effective ≠ universal、scene 選択 + workload analysis 必須」と honest framing。
half3 per-pixel accumulator が low-T 領域 (alpha * T < 6e-5) で underflow → 寄与 splat の累積消失で PSNR -10.0 dB。さらに half↔float cast が compute bound でも重く wallclock +75%。Apple Silicon SIMD は half と float が同 throughput、bandwidth bound でないので f16 化は loss-only。
NFS 共有 gsplat-env を異 sm 機 (c33 sm_86 → c32 sm_70) に持ち込み、TORCH_CUDA_ARCH_LIST=7.0 で JIT 再 build 1 回 (93s) → 即動作。Lego 1k iter で wallclock 10.5s / val PSNR 19.81 dB。30k full は Phase 2b。
原著 3DGS を V100 で 30k 学習 (PSNR 28.38 dB / 10m37s / 237k splats)。同 V100・同 30k で brush (wgpu→Vulkan) 8m24s / 37.46 dB を上回れず、抽象コスト ≪ 実装最適化レベル を CUDA 機でも再確認。さらに codebase eval と paper-standard eval で 12 dB 乖離 (28.4 vs 14.6) を発見、A.5 表は eval convention 注記必須。
10k iter で PSNR 24.007 dB を達成、30k baseline (mean 24.834) の 96.7% 品質、wallclock 1/3.4。15k → 23.932、20k → 23.868、25k → 24.623 と non-monotonic で kerbl_exp_decay lr schedule の max_steps 依存性 artifact が混入。卒論モバイル含意では「10k iter で十分、追加 iter は variance noise」と言える反面、E.5 として「fair な iter scaling 比較には固定 schedule での checkpoint 取得が必要」と spec 化が必要。
lego では capacity 50k から 1M まで PSNR は 24.605 〜 25.275 dB で variance σ ±0.32 dB band 内、capacity effect は実質ゼロ。final splats は 50k 飽和 → 81k → 85k → 84k と「本質的 ~85k で plateau」を実証。モバイル制約下で capacity 50-100k を choose しても 1M と同等品質、卒論モバイル章の重要数値。capacity 大きいほど refine が無駄 split で variance noise を増やす副作用も観測。
splat workspace は Rust 8,467 + Metal 2,230 LOC (合計 ~10.7k)、67 unit test 完備、findings ノート 10 件と Cloudflare Pages + R2 配信が稼働。卒論 §4.1 (実装規模) と §4.1.3 (shader 内訳) への直接転記に使える。
wgpu 抽象は自作 native より遅いはず、という想定が逆。同一 M4 Max 上で brush (wgpu) が 9m08s / 37.40 dB、自作 (Metal 直) が 26m32s / 26.27 dB。第 2 軸 (抽象コスト定量化) の主張を再 framing する必要が確定。
SGLD gate を paper 式に揃えた結果 mean_noise_weight が ~50-150x スケールズレし、calibration 補正 (5e5→5e3) でも iter 240 前後で SIGSEGV。Bisect smoke で真因が L1 全滅 → refine prune → 空 buffer crash というアルゴリズム順序問題と判明。Calibration ≠ correctness。
c33 (A6000, sm_86) に gsplat-env / orig3dgs-env / Rust + brush の 3 env を build。NFS 共有ホーム経由で c32 / c34 にも継承可能。3 env とも import / --help / --version レベルで動作確認 OK。実 training (Lego 30k) は Phase 2 で。
三層対比 (自作 M4 / brush V100 / CUDA V100) で wgpu→Vulkan が 37.46 dB / 8m24s と CUDA orig (28.4) / gsplat (32.9) より高 PSNR + 高速、自作 24.84 / 23m40s に対し brush wgpu→Metal が 37.40 / 9m08s。「wgpu 抽象は重い」の素朴予想が 2 機種で逆転し、第 2 軸の主張を『抽象コスト < 実装最適化レベル』に再 framing 必須。
本実装の MCMC が論文と乖離している 3 箇所 (5% incremental growth 欠如、λ_Σ/λ_o covariance/opacity 正則化欠如、relocation が refine prune に便乗) を整理し、A.2 の修正項目と検証条件を確定させた spec。
3 ストーリー (scale_reg 3 連敗 / MCMC 4 連敗 / #5.31 ArgBuffer 却下 → M-3.x 偶発発見) を「事前 commit gate に基づく honest reject が engineering 上の時間配分を保護し、失敗の数字自体が次に必要な infrastructure の signal を encode する」という方法論として整理。M-3.x baseline と第 3 軸 (unified memory) narrative はいずれもこの経路で確定。
refs.bib は Zotero auto-export なので手動編集禁止。A.2 MCMC 関連 (Kheradmand 2024) と D.9 Phase 1D サーベイ補追を Zotero 側に取り込む TODO リスト。
新 splat workspace は M-3.x の training quality (PSNR 24.842 dB) を variance band 内で再現、全 7 kernel + refine + Adam + eval + PLY save が動作。wallclock は +9.6% の軽微 regression (steady-state では +4%) で許容内。
30s Metal System Trace で 14,909 encoder / iter 40 encoder を観測。当初の「STIME 70% = sync overhead」解釈は B-mini プロト (scatter wait 削除、< 1% 改善) で撤回。真の breakdown は GPU compute ~70% / CPU encoding ~30%、dispatch fusion ROI は小さく Phase 4 後続 (C/D/F) 進行に戻る判断。
kernel-level GPU timer で rasterize_backwards が 24.1 ms/call / 52.1% total と確定 dominant。atomic float add が律速と判定し、step 33 SIMD prefix sum reduction prototype の最有力ターゲットを確定。期待 ROI は 50% 削減で iter -13%、80% 削減で -21%。
ArgBuffer は CPU encoding 寄与 0.5% で 3% gate 不通過 → reject。queue reuse refactor 単独で -13.7% wallclock (1.14 ms/iter 削減が autorelease pool 圧縮を伴って効果増幅)。真の bottleneck は host-side loss compute + readback ~10.5 ms/iter (= 24-26% wallclock potential)、第 3 軸 narrative 最強の #5.31.x GPU loss kernel + no-readback を次着手に再定義。
host pump pipeline を排除し forward/loss/backward を GPU buffer で連結。2k iter wallclock -26.9% (42.5 → 31.07 ms/iter)、30k では n=4 variance test で wallclock -14〜-19% を再現。当初の PSNR -0.65 dB regression 主張は撤回 (band 25.0 ± 0.6 dB 内)。第 3 軸 (unified memory) narrative の核。