Round 25 Track C (argon-r25-moemm-down-and-plan): mm_down3 W4<T_Q2_0> 64-Block Stepping + mm_gu3 Coalesced half4 HS Store #

1. Summary of Shipped Changes #

  1. W4<T_Q2_0>::run_q<OFF>(device const uchar* b, uint kl4) & mm_down3 64-Element Block Stepping (metal/kernels/moe_mm.metal):

    • In mm_down3 (F == T_Q2_0 && TK == 32, coop_k4), two consecutive TK = 32 steps (k0 and k0 + 32) sit inside the same 64-element, 18-byte Q2_0 block (QK = 64, BB = 18).
    • Previously, each k0 += 32 iteration computed boff = uint(k0 >> 6) * 18 and j_in = (k0 + kl) & 63, and W8<T_Q2_0> called W4<T_Q2_0>::run(rdw, j_in) and W4<T_Q2_0>::run(rdw, j_in + 16), where the second call had to recompute + ((k >> 6) * 18) and 2 + ((k & 63) >> 2) because the compiler could not prove (j_in + 16) < 64.
    • By stepping k0 += 64, w0_l += 18 and introducing W4<T_Q2_0>::run_q<OFF>(device const uchar* b, uint kl4) reading (b + kl4)[OFF] with compile-time constant immediate byte offsets OFF in {2, 6, 10, 14} and unsigned kl4 = uint(kl) >> 2 (eliminating 32-to-64-bit sign extension sext, (k >> 6) * 18, and (k & 63) while keeping the minimal 1-W4 VGPR live range across the 8-row unroll), mm_down3 speeds up by +2.48% (-121.4 us/layer, -5.83 ms across 48 layers) at T = 1024 and +1.85% (-146.1 us/layer, -7.01 ms across 48 layers) at T = 2048, with +0.15% at T = 512.
  2. mm_gu3 half4 Coalesced HS Store Pointer Hoisting + Format Expansion (metal/kernels/moe_mm.metal):

    • Hoisted threadgroup const float4* ot_p = (threadgroup const float4*)(&ot[sg][mr * TN + f]); and device half* hs_p = HS + ulong(row0 + mr) * a.n_ff + n0 + f; with stride hs_step = uint(RP) * a.n_ff out of the unrolled m store loop in mm_gu3.
    • Enabled the coalesced half4 HS store path for T_IQ3_XXS, T_IQ2_XXS, and T_Q2_0 in addition to T_IQ2_XS (+0.09% on IQ2_XS, +0.33% on IQ3_XXS, +0.91% on IQ2_XXS, +0.60% on Q2_0 at T = 1024).
  3. moe_mm_parity Paired A/B Harness (metal/tests/moe_mm_parity.cpp):

    • Added candidate warmup and alternating (i & 1) A/B ordering to gather_bench plan timing (7 paired iterations).
    • Updated --ab isolated kernel benchmarking (--gu-bench / --dn-bench) to run 19 interleaved pairs with external-contention spike filtering (<= 1.10 * best_pair).

2. Measured A/B Results on Apple M5 #

All benchmarks run with STRATA_METAL_KERNELS=/tmp/argon_r25_moemm/strata/metal/kernels (A = candidate) and --ab /tmp/argon_r25_moemm/base_kernels (B = baseline):

Benchmark T Candidate A med (min) Baseline B med (min) Speedup diff med (min) Bitwise Parity
mm_down3 (IQ2_XS/Q2_0, --dn-bench) 512 3572.3 us (3561.6 us) 3577.5 us (3558.6 us) +0.15% (-0.08%) HS/YE/Y memcmp=PASS
mm_down3 (IQ2_XS/Q2_0, --dn-bench) 1024 4898.7 us (4886.9 us) 5020.1 us (5006.3 us) +2.48% (+2.44%) HS/YE/Y memcmp=PASS
mm_down3 (IQ2_XS/Q2_0, --dn-bench) 2048 7914.2 us (7883.8 us) 8060.3 us (8033.7 us) +1.85% (+1.90%) HS/YE/Y memcmp=PASS
mm_gu3 (IQ2_XS/Q2_0, --gu-bench) 512 7758.1 us (7725.8 us) 7754.5 us (7733.6 us) -0.05% (+0.10%) HS/YE/Y memcmp=PASS
mm_gu3 (IQ2_XS/Q2_0, --gu-bench) 1024 12921.2 us (12842.6 us) 12933.4 us (12846.8 us) +0.09% (+0.03%) HS/YE/Y memcmp=PASS
mm_gu3 (IQ2_XS/Q2_0, --gu-bench) 2048 22222.1 us (22044.8 us) 22229.8 us (22035.1 us) +0.03% (-0.04%) HS/YE/Y memcmp=PASS
mm_gu3 (IQ2_XXS/Q2_0, --gu-bench) 1024 13530.1 us (13403.5 us) 13653.8 us (13544.2 us) +0.91% (+1.05%) HS/YE/Y memcmp=PASS
mm_gu3 (Q2_0/Q2_0, --gu-bench) 1024 9455.1 us (9419.9 us) 9512.1 us (9470.1 us) +0.60% (+0.53%) HS/YE/Y memcmp=PASS
mm_gu3 (IQ3_XXS/Q2_0, --gu-bench) 1024 13664.5 us (13537.5 us) 13710.0 us (13586.5 us) +0.33% (+0.36%) HS/YE/Y memcmp=PASS
gather-bench (mm_plan + mm_gather_h) 2048 plan 51.16 us, tg256 1228.1 us plan 51.14 us, tg256 1233.2 us +0.42% all 8 plan + XS PASS

3. Ruled-Out Hypotheses (Measured Regressions / Neutral) #

  • Sharing d and loading q0, q1 upfront in W8<T_Q2_0>: -0.84% at T=1024, -1.39% at T=2048 (increases VGPR live ranges across the 8-row unrolled loop).
  • SWAR 0x40100401u multiply in W4<T_Q2_0>: -0.65% at T=1024, -2.58% at T=2048 (adds 4 fp32 fadd -1.0f ops on the FPU pipe).
  • SWAR 0x00204081u char4 sign negation in w4_signed: -10.11% at T=1024 (serializes float4 conversion behind sign4_iq2xs + 32-bit integer multiplies).
  • Unrolling k0 by 2 (k0 += 64) in mm_gu3: -1.22% at T=1024, -3.42% at T=512 (mm_gu3 already has 2 i loops and 2 op.run calls per k0 step; doubling it to 4 spills VGPRs).
  • Adding #pragma clang loop unroll(full) on acc / accg zero-init loops: -0.10% to -0.40% vs leaving MPP's cooperative tensor loop default.

4. Artifact Paths #

  • Clean unified diff (git -C vendor/strata apply --check verified): /tmp/argon_r25_moemm/argon_r25_moemm.patch
  • Audit report: audits/argon_r25_moemm.md