Round 22 Track C Audit Report: moe_down (T_Q2_0R/T_Q2_0) Compressed-Register Weight Reuse & moe_route / plan_body Optimization #
- Agent:
argon-moe-down-q2r-and-route(gemini-4-argon) - Scratch workspace:
/tmp/argon_r22_moe/strata - Unified patch:
/tmp/argon_r22_moe/argon_r22_moe.patch(git -C vendor/strata apply --checkclean, exit code0) - Files modified:
metal/kernels/moe.metal,metal/tests/expert_parity.cpp
1. Key Findings & Design #
1.1 dn_body & gu_body: Compressed-Register Weight Reuse (q2_combine<F>) Across NR & NE #
Previously, in dn_body (metal/kernels/moe.metal):
- Holding
float q[NR][16]; float4 sc[NR];(40registers forNR = 2) acrossr = 0..NR-1spilled registers on Apple M5 whenNE >= 2, which forceddn_bodyforF == T_Q2_0 || F == T_Q2_0Rto placeras the outer loop and reloadxs[16]fromhNR = 2separate times per tokent. - In
gu_body,F == T_Q2_0atNE >= 2reloadedxs[16]2 * NR = 4times per tokent(g0andu0for eachr).
By introducing q2_combine<F>(ushort2 pk, float d, thread const float* xs, float xsum0):
- Compressed register staging (
4registers total forNR = 2indn_body,8ingu_body):- In
dn_body(F == T_Q2_0 || F == T_Q2_0R, across allNE = 1..4), we pre-loadushort2 pk[NR]; float d[NR];for allr = 0..NR-1first (sharing(u >> 2) * 18and2 + 4 * (u & 3)across rows), then loopfor (int t = 0; t < NE; ++t), loadingX<F>::load(h + (c + t) * int(a.n_ff), ...)once per tokent(-50%hdevice loads atNR = 2, NE >= 2) and accumulatingac[r][t] += q2_combine<F>(pk[r], d[r], xs, xsum[0])without ever materializingfloat q[16]. - In
gu_body(F == T_Q2_0 || F == T_Q2_0R,NE >= 2), we pre-loadpkg[NR], pku[NR], dg[NR], du[NR](8registers forNR = 2), loadX<F>::loadonce per tokent(-75%xloads atNR = 2, NE >= 2), and accumulateag[r][t]andau[r][t]viaq2_combine<F>. - Added
#pragma clang loop unroll(full)to ther < NRandt < NEloops indn_bodyandgu_body(keepingr < NRun-pragmad ingu_bodywhenUNIT == 32to avoidqg[32]/qu[32]register pressure inQ4_K).
- In
- Exact IEEE-754 safe-math bitwise parity:
q2_combine<F>preserves the exact 4-way FMA accumulation order (s0, s1, s2, s3) and scale/offset expression ofDec<F>::run+unit_combine<16>, achievingstd::memcmp == 0across every buffer (plan,h,ye,y).
1.2 moe_route & plan_body: v[16] Indexing Hypothesis Falsified, sg == 0 Parallel SIMD Prefix Sum Shipped #
- Falsified hypothesis (
v[ex / 32] = -INFINITY-> 16-wayif (i == wi)loop):- Tested in isolation on Apple M5 (
route_parity --ab): replacingv[ex / 32] = -INFINITY;with#pragma clang loop unroll(full) for (int i = 0; i < 16; ++i) if (i == wi) v[i] = -INFINITY;regressedmoe_routeby +22% to +54% (5.12 us -> 7.89 usatntok=1 split=0,6.95 us -> 9.76 usatntok=1 split=1). - Root cause: Apple Silicon GPU hardware supports native register-indirect indexing on
v[ex / 32] = -INFINITY;(1 instruction in the winning lane), whereas the 16-wayif (i == wi)loop emits 16 compare/select instructions per rank (160 extra instructions across 10 ranks) and increases live scalar register pressure in the 512-thread (16-simdgroup) threadgroup. Rejected per rule ("Only ship changes that are proven net wins on M5").
- Tested in isolation on Apple M5 (
- Proven win in
plan_body(used bymoe_route,moe_plan, androuter_route):- Previously, after the first
threadgroup_barrier, threadtid == 0executed a serial2 x 16 = 32-iteration loop reading and writings_grpands_entin threadgroup memory while the other 511 threads waited at the barrier, and unconditionally ransimd_prefix_exclusive_sum(miss)/c1even when!split. - Replaced the
tid == 0serial loop with a single-instruction parallelsimd_prefix_exclusive_sumacrosssg == 0(lane < nsg) and gated thesplitsecond-half prefix sums onsplit, cuttingmoe_routetime by -8.8% to -22.7% andmoe_plantime by -14.6% to -35.4% acrossntok = 1..8.
- Previously, after the first
2. Verification & Paired A/B Benchmarks on Apple M5 #
2.1 Bitwise Parity (std::memcmp == 0) #
route_parity: K=512 (200 windows)0mismatches, K=256+MoCE=0.85 (200 windows)0mismatches (PASS).route_parity --ab /tmp/argon_r22_moe/moe_ref.metal: 200 trials (moe_route+moe_plan,split = 0, 1,ntok = 1..8):0 fail(s) ALL PASS.expert_parity --ab /tmp/argon_r22_moe/moe_ref.metal:Q2_0/Q2_0(142),IQ2_XS/Q2_0(prep),IQ3_XXS/Q5_1,Q4_K/IQ4_NLacrossNE = 1, 2, 3, 4, 8 (same)andntok = 1, 2, 3, 4, 8 (random):0 fail(s) ALL PASS(memcmp == 0onplan,h,ye,y).
2.2 Paired Interleaved A/B Benchmarks (expert_parity --ab ... --bench) #
A. Q2_0 Gate/Up (32,2,4) + T_Q2_0R (142) Down (moe_down_142_8_2_4) #
| Case | Groups | dn Base (us) |
dn Cand (us) |
dn Ratio |
gu Base (us) |
gu Cand (us) |
gu Ratio |
|---|---|---|---|---|---|---|---|
NE=1 (same) |
10.0 | 47.2 | 46.0 | 0.9735 (-2.6%) | 74.9 | 73.7 | 0.9907 (-0.9%) |
NE=2 (same) |
10.0 | 64.1 | 59.1 | 0.9229 (-7.7%) | 110.9 | 97.3 | 0.8777 (-12.2%) |
NE=3 (same) |
10.0 | 82.8 | 75.7 | 0.9143 (-8.6%) | 174.0 | 134.8 | 0.7753 (-22.5%) |
NE=4 (same) |
10.0 | 106.0 | 96.9 | 0.9151 (-8.5%) | 219.1 | 174.1 | 0.7940 (-20.6%) |
ntok=1 sh=0.3 |
10.0 | 47.2 | 46.0 | 0.9755 (-2.5%) | 73.0 | 73.0 | 0.9995 (-0.1%) |
ntok=2 sh=0.3 |
17.5 | 82.7 | 80.6 | 0.9746 (-2.5%) | 127.3 | 126.3 | 0.9899 (-1.0%) |
ntok=4 sh=0.3 |
31.0 | 151.1 | 144.3 | 0.9539 (-4.6%) | 234.9 | 225.9 | 0.9618 (-3.8%) |
ntok=8 sh=0.3 |
59.2 | 290.3 | 274.6 | 0.9452 (-5.5%) | 461.8 | 435.0 | 0.9424 (-5.8%) |
B. IQ2_XS Gate/Up (32,2,4) + T_Q2_0 (prep) Down (moe_down_134_8_2_4) #
| Case | Groups | dn Base (us) |
dn Cand (us) |
dn Ratio |
gu Base (us) |
gu Cand (us) |
gu Ratio |
|---|---|---|---|---|---|---|---|
NE=1 (same) |
10.0 | 45.4 | 44.6 | 0.9843 (-1.6%) | 101.8 | 93.4 | 0.9176 (-8.2%) |
NE=2 (same) |
10.0 | 65.6 | 55.1 | 0.8394 (-16.1%) | 135.0 | 117.5 | 0.8702 (-13.0%) |
NE=3 (same) |
10.0 | 86.0 | 76.9 | 0.8937 (-10.6%) | 197.5 | 163.7 | 0.8293 (-17.1%) |
NE=4 (same) |
10.0 | 112.4 | 97.7 | 0.8688 (-13.1%) | 251.9 | 232.4 | 0.9223 (-7.8%) |
ntok=1 sh=0.3 |
10.0 | 45.5 | 44.6 | 0.9805 (-1.9%) | 102.0 | 93.6 | 0.9175 (-8.3%) |
ntok=2 sh=0.3 |
17.5 | 77.2 | 74.8 | 0.9673 (-3.3%) | 183.1 | 166.6 | 0.9104 (-9.0%) |
ntok=4 sh=0.3 |
31.0 | 136.6 | 131.3 | 0.9611 (-3.9%) | 341.5 | 310.6 | 0.9094 (-9.1%) |
ntok=8 sh=0.3 |
59.2 | 260.6 | 245.3 | 0.9429 (-5.7%) | 662.2 | 601.5 | 0.9086 (-9.1%) |
C. moe_route & moe_plan Paired A/B (route_parity --ab ... --bench) #
| Kernel | split |
ntok |
Base (us) | Cand (us) | Ratio | 48-Layer Savings |
|---|---|---|---|---|---|---|
moe_route |
0 | 1 | 5.15 | 3.98 | 0.7727 (-22.7%) | 0.247 -> 0.191 ms |
moe_route |
0 | 2 | 5.68 | 4.53 | 0.7956 (-20.4%) | 0.273 -> 0.217 ms |
moe_route |
0 | 4 | 7.18 | 6.01 | 0.8377 (-16.2%) | 0.345 -> 0.289 ms |
moe_route |
0 | 8 | 9.87 | 8.79 | 0.8889 (-11.1%) | 0.474 -> 0.422 ms |
moe_plan |
0 | 1 | 3.07 | 1.99 | 0.6464 (-35.4%) | 0.147 -> 0.095 ms |
moe_plan |
0 | 2 | 3.68 | 2.60 | 0.7070 (-29.3%) | 0.176 -> 0.125 ms |
moe_plan |
0 | 4 | 5.06 | 3.98 | 0.7837 (-21.6%) | 0.243 -> 0.191 ms |
moe_plan |
0 | 8 | 7.26 | 6.21 | 0.8541 (-14.6%) | 0.348 -> 0.298 ms |
moe_route |
1 | 1 | 6.94 | 5.97 | 0.8564 (-14.4%) | 0.333 -> 0.286 ms |
moe_route |
1 | 2 | 7.43 | 6.44 | 0.8656 (-13.4%) | 0.357 -> 0.309 ms |
moe_route |
1 | 4 | 8.61 | 7.59 | 0.8842 (-11.6%) | 0.413 -> 0.364 ms |
moe_route |
1 | 8 | 11.52 | 10.50 | 0.9117 (-8.8%) | 0.553 -> 0.504 ms |