[{"data":1,"prerenderedAt":238},["ShallowReactive",2],{"finding:phase5-step30-profile":3,"finding-runs:phase5-step30-profile":236,"finding-related:phase5-step30-profile":237},{"meta":4,"impact":26,"sections":31},{"id":5,"title":6,"subtitle":7,"eyebrow":8,"date":9,"status":10,"category":11,"polarity":12,"axes":13,"tags":15,"task_code":23,"related_runs":24},"phase5-step30-profile","Phase 5 step 30 — Instruments \u002F Metal System Trace 分析結果","30s recording で 14,909 encoder \u002F iter 約 40 encoder を観測。当初は STIME 70% = sync overhead と解釈したが、B-mini プロト (scatter wait_until_completed 削除) で iter 速度が \u003C 1% しか変わらず仮説撤回。真の time breakdown は GPU compute ~70% \u002F CPU encoding ~30%、fusion ROI は小さい。","Phase 5 · step 30 profile","2026-04-30","stable","speed","mixed",[14],3,[16,17,18,19,20,21,22],"phase-5","step-30","instruments","metal-system-trace","m4-max","profiling","fusion-reject","#5.30",[25],"phase5-step30",{"summary":27,"rank":28,"verdict":29,"delta_wallclock":30},"30s Metal System Trace で 14,909 encoder \u002F iter 40 encoder を観測。当初の「STIME 70% = sync overhead」解釈は B-mini プロト (scatter wait 削除、\u003C 1% 改善) で撤回。真の breakdown は GPU compute ~70% \u002F CPU encoding ~30%、dispatch fusion ROI は小さく Phase 4 後続 (C\u002FD\u002FF) 進行に戻る判断。","mid","investigative","B-mini: -1% (noise floor)",[32,35,50,53,87,89,118,120,122,129,131,137,139,142,144,146,148,154,156,158,160,162,164,166,171,199,201,203,207,210,212,214,218,220,222,224,229,231,233],{"type":33,"text":34},"lead","Phase 5 step 30 で M4 Max 上の 30s Metal System Trace を取得 (646MB bundle)。1 iter で約 \u003Cstrong>40 個の Metal encoder\u003C\u002Fstrong> を作成、CPU 時間の 70% が syscall (\u003Ccode>mach_msg_trap\u003C\u002Fcode>)。当初は「dispatch sync が dominant な遅さの主因」と判断し step 31.5 軽量 fusion を推奨したが、B-mini プロト (scatter \u003Ccode>wait_until_completed\u003C\u002Fcode> 削除) で iter 速度がほぼ変わらず (\u003C 1% 改善) → 解釈の誤りを発見。",{"type":36,"items":37},"kv",[38,41,44,47],{"key":39,"value":40},"取得","2026-04-30 08:22:11 〜 08:22:42 (30.9 sec recording)",{"key":42,"value":43},"設定","F config + L1+SSIM (λ=0.20)、500 iter で起動 (--time-limit で 30s で停止)",{"key":45,"value":46},"Trace bundle","3dgs-rs\u002Fruns\u002Fphase5-step30\u002Fprofile-30s-lam0.20.trace (646MB、gitignored、local 保管)",{"key":48,"value":49},"Hardware","M4 Max、macOS 26.3.1",{"type":51,"text":52},"heading","主要数値",{"type":54,"columns":55,"align":59,"rows":62},"table",[56,57,58],"指標","値","補足",[60,61,60],"left","right",[63,67,71,75,79,83],[64,65,66],"取得 iter 数","~375","30s ÷ 80ms\u002Fiter",[68,69,70],"総 encoder 数","14,909","metal-application-encoders-list table",[72,73,74],"encoders\u002Fiter","~40","これが想定外に多い",[76,77,78],"Trace bundle サイズ","646MB","finalize 後 (raw 3.5GB → 圧縮)",[80,81,82],"GPU execution points","520,546","個別 GPU event (詳細すぎ、集計困難)",[84,85,86],"CPU samples (timer fired)","10,777","1ms 周期、Running 時のみ捕捉",{"type":51,"text":88},"補足: 事前 ps 診断 (28-C-1 sweep 中の lam0.10 process)",{"type":54,"columns":90,"align":92,"rows":93},[56,57,91],"含意",[60,61,60],[94,98,102,106,110,114],[95,96,97],"%CPU","47.9%","単スレッド換算で 0.5 core 程度",[99,100,101],"UTIME (user time)","1:13.56","Rust app 自身の計算",[103,104,105],"STIME (system time)","2:41.94","kernel\u002Fsyscall = mach_msg_trap (wait_until_completed)",[107,108,109],"STIME \u002F (UTIME + STIME)","70%","CPU 時間の 7 割が GPU 同期待ち (初期解釈、後に撤回)",[111,112,113],"Wall time","746s","lam0.10 全 10k iter",[115,116,117],"総 CPU time \u002F Wall time","31.5%","残 68.5% は GPU active or 全体 idle",{"type":51,"text":119},"解釈 (初版)",{"type":51,"level":14,"text":121},"確定した事実",{"type":123,"ordered":124,"items":125},"list",true,[126,127,128],"\u003Cstrong>1 iter で約 40 個の Metal encoder を作成\u003C\u002Fstrong> — 想定 (10 commit × ~3 encoder) を大幅超過。各 encoder は別々の \u003Ccode>commit() + wait_until_completed()\u003C\u002Fcode> cycle を伴う","\u003Cstrong>CPU 時間の 70% が syscall (STIME)\u003C\u002Fstrong> — \u003Ccode>mach_msg_trap\u003C\u002Fcode> 経由の \u003Ccode>wait_until_completed()\u003C\u002Fcode> が dominant、Rust user code は CPU 時間の 30% のみ","\u003Cstrong>wall time 全体の ~22% が syscall に消えている\u003C\u002Fstrong> — 31.5% × 70% = 22%、80ms\u002Fiter のうち ~17.6ms が syscall overhead (初期推論、後に誤りと判明)",{"type":51,"level":14,"text":130},"推定 (初版、後に撤回)",{"type":123,"items":132},[133,134,135,136],"残 78ms\u002Fiter の内訳は \u003Cstrong>CLI ツール (Instruments.app GUI) なしには直接見えない\u003C\u002Fstrong>","14k 個の encoder と 70% syscall 率から、\u003Cstrong>dispatch sync が dominant な遅さの主因\u003C\u002Fstrong> と判断","step 32 (MTLIndirectCommandBuffer) で 40 dispatch を 1 commit に統合 → syscall overhead 17.6ms → ~2-3ms、期待 iter 速度 80ms → \u003Cstrong>40-50ms\u003C\u002Fstrong> (1.6-2× 高速化)","step 33-35 まで進めば 15-20ms\u002Fiter まで下がる見込",{"type":51,"level":14,"text":138},"B (step 31.5 軽量 fusion) vs full step 32",{"type":140,"text":141},"paragraph","\u003Cstrong>step 31.5\u003C\u002Fstrong> (1 iter 1 commit にする、IndirectCommandBuffer なし、共有 cmd buffer 引数化): 工数 2-3 日、期待 iter 速度 80ms → 40-50ms (step 32 と同等の効果)、ICB なしでも cmd buffer fusion だけで主要効果は得られる、と推定。",{"type":140,"text":143},"\u003Cstrong>full step 32\u003C\u002Fstrong> (ICB + 動的 dispatch chain): 工数 1 週間、期待 iter 速度は step 31.5 と同程度、ただし dynamic refine やスケール時にメリット。現状の固定 iter loop なら step 31.5 で十分、と推定 (後に B-mini で撤回)。",{"type":51,"text":145},"次の判断 (Step 7、初版)",{"type":140,"text":147},"\u003Cstrong>選択肢 B\u003C\u002Fstrong> (step 31.5 軽量 fusion) を推奨。理由:",{"type":123,"ordered":124,"items":149},[150,151,152,153],"期待効果が full step 32 とほぼ同じ","工数 2-3 日 vs 1 週間","Phase 4 後続 D\u002FF の sweep 時間が大幅短縮 (28-C-1 60 min → 12-15 min 想定)","dev 体験の質的向上が dev velocity に効く",{"type":140,"text":155},"ただし以下は事前確認が必要: gradient check が fusion 後も全 pass する保証、ssim.rs の独立 cmd buffer use case (training context 外) を残す設計、run-time impact: H baseline (22.42 dB) を fusion 後に再走させて bit-identical 検証 (atomic 順序変化で ±ULP は許容)。",{"type":51,"text":157},"Instruments.app GUI 分析 (推奨追加 step)",{"type":140,"text":159},"CLI 抽出ではカバー仕切れない情報: CPU\u002FGPU 同時タイムライン (どこで GPU が idle 待ちか)、\u003Ccode>mach_msg_trap\u003C\u002Fcode> の callstack (どの Rust 関数が wait してるか)、per-encoder GPU 実行時間ヒストグラム、thermal throttling 時刻と GPU clock 推移。\u003Ccode>open runs\u002Fphase5-step30\u002Fprofile-30s-lam0.20.trace\u003C\u002Fcode> で Instruments.app に開いて視覚分析推奨。所要 15-30 分。",{"type":51,"text":161},"実験結果と解釈の訂正 (2026-04-30 追記)",{"type":51,"level":14,"text":163},"実験: scatter wait_until_completed 削除 (B-mini プロト)",{"type":140,"text":165},"\u003Ccode>gpu_tile.rs::radix_sort\u003C\u002Fcode> で \u003Ccode>buf_shift\u003C\u002Fcode> を 16 個独立 buffer に分離 (race 回避)、中間 pass の scatter \u003Ccode>wait_until_completed\u003C\u002Fcode> を削除、最終 pass のみ残す。同 queue 内 cmd buffer は GPU 上で順次実行されるため、論理的には wait 不要。",{"type":167,"label":168,"variant":169,"text":170},"callout","結果: iter 速度ほぼ変わらず","warn","下表のとおり改善幅 \u003C 1%、noise floor (±0.3 ms) 内。unit test 7\u002F7 全 pass。",{"type":54,"columns":172,"align":177,"rows":178},[173,174,175,176],"iter","pre-fusion","post-fusion","差",[61,61,61,61],[179,184,189,194],[180,181,182,183],200,"73.3 ms","72.2 ms","-1.1 ms",[185,186,187,188],500,"64.5 ms","63.7 ms","-0.8 ms",[190,191,192,193],800,"60.3 ms","60.4 ms","+0.1 ms",[195,196,197,198],1000,"61.6 ms","63.1 ms","+1.5 ms",{"type":51,"level":14,"text":200},"解釈の修正",{"type":140,"text":202},"過去の解釈には 2 つの誤りがあった:",{"type":167,"label":204,"variant":205,"text":206},"誤解 1: wait_until_completed 削除 = sync overhead 削減","danger","\u003Cstrong>実際\u003C\u002Fstrong>: 同 queue 内 cmd buffer は既に GPU 上で順次実行されている。\u003Ccode>wait_until_completed\u003C\u002Fcode> は CPU 側の観測ポイントを変えるだけで、GPU 待ち時間自体は短縮しない。次 cmd buffer の wait で結局 GPU 完了を待つことになる。",{"type":167,"label":208,"variant":205,"text":209},"誤解 2: STIME 70% = 節約可能な sync overhead","\u003Cstrong>実際\u003C\u002Fstrong>: STIME は CPU が kernel mode で実行してる時間 (encoding, mach IPC processing)。CPU が \u003Ccode>wait_until_completed\u003C\u002Fcode> で blocked してる時間は STIME に \u003Cstrong>入らない\u003C\u002Fstrong> (Blocked state)。「22% wall time = 同期 overhead」は誤った推論。",{"type":51,"level":14,"text":211},"真の time breakdown (再評価)",{"type":140,"text":213},"80ms\u002Fiter の内訳:",{"type":123,"items":215},[216,217],"\u003Cstrong>~55ms (~70%) = GPU compute\u003C\u002Fstrong> ← CPU は blocked、GPU が物理的に計算","\u003Cstrong>~25ms (~30%) = CPU 側 encoding + buffer mapping + IPC processing\u003C\u002Fstrong>",{"type":140,"text":219},"\u003Cstrong>fusion で削れるのは 25ms 内のごく一部のみ\u003C\u002Fstrong>。GPU compute 部分は kernel-level 最適化が必要。",{"type":51,"level":14,"text":221},"結論: B-mini ROI ゼロ、A (Phase 4 後続続行) に戻る",{"type":140,"text":223},"dispatch 系の最適化は GPU compute bottleneck の状況では効かない。後続の path:",{"type":123,"items":225},[226,227,228],"\u003Cstrong>A に戻り Phase 4 後続 C\u002FD\u002FF を進める\u003C\u002Fstrong> ← 採択","本格 Phase 5 着手時は \u003Cstrong>Shader Timeline 有効で再 profile\u003C\u002Fstrong> → kernel-level hot path 特定 → 個別最適化 (atomic 削減、SIMD reduction 等)","step 31.5 の fusion 案は \u003Cstrong>future work\u003C\u002Fstrong> または \u003Cstrong>step 32 (ICB) の前段としてのみ価値\u003C\u002Fstrong>",{"type":51,"level":14,"text":230},"コード状態",{"type":140,"text":232},"\u003Ccode>gpu_tile.rs\u003C\u002Fcode> の変更 (buf_shift 16 buffer 化 + scatter wait 部分削除) は \u003Cstrong>commit 済\u003C\u002Fstrong>: 正しさは保たれている (unit test 7\u002F7 pass)、速度向上は微小だが、コードはより明示的になった (race 回避策が文書化されている)、後の最適化作業で base point として再利用可能。",{"type":167,"label":234,"variant":169,"text":235},"Lesson","Profile 数値の解釈は実験で裏取りすること。STIME ≠ GPU 同期待ち、wait_until_completed 削除 ≠ sync overhead 削減。kernel-level の per-call timing (step 30b) が必要 → step 30b でその場で rasterize_backwards 24ms\u002Fcall が dominant と判明する流れに繋がる。",[],[],1782449788677]