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 #
-
W4<T_Q2_0>::run_q<OFF>(device const uchar* b, uint kl4)&mm_down364-Element Block Stepping (metal/kernels/moe_mm.metal):- In
mm_down3(F == T_Q2_0 && TK == 32,coop_k4), two consecutiveTK = 32steps (k0andk0 + 32) sit inside the same 64-element, 18-byteQ2_0block (QK = 64, BB = 18). - Previously, each
k0 += 32iteration computedboff = uint(k0 >> 6) * 18andj_in = (k0 + kl) & 63, andW8<T_Q2_0>calledW4<T_Q2_0>::run(rdw, j_in)andW4<T_Q2_0>::run(rdw, j_in + 16), where the second call had to recompute+ ((k >> 6) * 18)and2 + ((k & 63) >> 2)because the compiler could not prove(j_in + 16) < 64. - By stepping
k0 += 64, w0_l += 18and introducingW4<T_Q2_0>::run_q<OFF>(device const uchar* b, uint kl4)reading(b + kl4)[OFF]with compile-time constant immediate byte offsetsOFF in {2, 6, 10, 14}and unsignedkl4 = uint(kl) >> 2(eliminating 32-to-64-bit sign extensionsext,(k >> 6) * 18, and(k & 63)while keeping the minimal 1-W4VGPR live range across the 8-row unroll),mm_down3speeds up by +2.48% (-121.4 us/layer,-5.83 msacross 48 layers) atT = 1024and +1.85% (-146.1 us/layer,-7.01 msacross 48 layers) atT = 2048, with+0.15%atT = 512.
- In
-
mm_gu3half4CoalescedHSStore Pointer Hoisting + Format Expansion (metal/kernels/moe_mm.metal):- Hoisted
threadgroup const float4* ot_p = (threadgroup const float4*)(&ot[sg][mr * TN + f]);anddevice half* hs_p = HS + ulong(row0 + mr) * a.n_ff + n0 + f;with stridehs_step = uint(RP) * a.n_ffout of the unrolledmstore loop inmm_gu3. - Enabled the coalesced
half4HSstore path forT_IQ3_XXS,T_IQ2_XXS, andT_Q2_0in addition toT_IQ2_XS(+0.09%onIQ2_XS,+0.33%onIQ3_XXS,+0.91%onIQ2_XXS,+0.60%onQ2_0atT = 1024).
- Hoisted
-
moe_mm_parityPaired A/B Harness (metal/tests/moe_mm_parity.cpp):- Added candidate warmup and alternating
(i & 1)A/B ordering togather_benchplan timing (7paired iterations). - Updated
--abisolated kernel benchmarking (--gu-bench/--dn-bench) to run19interleaved pairs with external-contention spike filtering (<= 1.10 * best_pair).
- Added candidate warmup and alternating
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
dand loadingq0, q1upfront inW8<T_Q2_0>:-0.84%atT=1024,-1.39%atT=2048(increases VGPR live ranges across the 8-row unrolled loop). - SWAR
0x40100401umultiply inW4<T_Q2_0>:-0.65%atT=1024,-2.58%atT=2048(adds 4 fp32fadd -1.0fops on the FPU pipe). - SWAR
0x00204081uchar4sign negation inw4_signed:-10.11%atT=1024(serializesfloat4conversion behindsign4_iq2xs+ 32-bit integer multiplies). - Unrolling
k0by 2 (k0 += 64) inmm_gu3:-1.22%atT=1024,-3.42%atT=512(mm_gu3already has 2iloops and 2op.runcalls perk0step; doubling it to 4 spills VGPRs). - Adding
#pragma clang loop unroll(full)onacc/accgzero-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 --checkverified):/tmp/argon_r25_moemm/argon_r25_moemm.patch - Audit report:
audits/argon_r25_moemm.md