Round 20 Track C Audit: gdn_pre Key-Head t >= 3 Vectorized conv_w Fast Path + gdn_scan_r 32-Bit Base Offset Hoisting & Final-Token Dead-Lookahead Elimination #

1. Summary of Changes (metal/kernels/gdn_prompt.metal) #

  1. gp_conv & gdn_pre Key-Head t >= 3 Fast Path (lines 26–105):

    • In gp_conv (t < 3 fallback), replaced 4 scalar cw[ch * 4 + k] loads with a single 128-bit float4 w = *(device const float4*)(cw + ch * 4); load and unrolled the 4-tap FMA loop.
    • In gdn_pre's key-head branch (if (x < k_tgs)), added a t >= 3 branchless fast path preserving the exact lane-to-channel mapping d = int(lane) + m * 32 (m = 0..3).
    • Hoisted pq = qkv + (t - 3) * C + kh * S + int(lane) and pk = qkv + (t - 3) * C + (hk_n + kh) * S + int(lane), loaded 128-bit float4 wq and wk from conv_w, and evaluated the 4-tap FMA chain at offsets 0, C, 2*C, 3*C without src >= 0 ternary branches.
  2. gdn_scan_r State Offset Hoisting, 32-Bit Base Offsets, and Final-Token Dead-Lookahead Elimination (lines 261–351, 421–423):

    • Hardware Register Discovery (64-bit VGPR vs 32-bit base offset): Holding 64-bit device pointers (sp, kn_p, qn_p, gb_p, vc_p, kq_p, o_p) live across the threadgroup_barrier inside the token scan loop consumes 2 VGPRs per pointer per lane on Apple Silicon, crossing an occupancy cliff (192.2 ms -> 197.8 ms).
    • Instead, hoisted 32-bit integer strides and base offsets (const int rs = hv * S, s0 = (i0 * hv + h) * S + j;, const int ks = hkn * S, k0 = hk * S + i0 + int(lr), v0 = h * S + j;), keeping device base pointers in uniform argument registers and indexing (state + s0)[i * rs], kn[tn * ks + k0 + c * 32], qn[tn * ks + k0 + c * 32], vc[tn * rs + v0], and o[t * rs + v0].
    • Split the TB == 0 loop into for (int t = 0; t < T - 1; ++t) (with tn = t + 1, eliminating min(t + 1, T - 1)) followed by a if (T > 0) final-token epilogue for t = T - 1 that skips the dead kn_l, qn_l, g_b_n, v_n global loads and skips the 64 dead simd_broadcasts (knr, qnr) and 64 dead ka/qa FMAs.

2. Bitwise Parity Verification (memcmp == 0) #

Verified via /tmp/argon_r20_gdn/strata/build-metal/gdn_prompt_parity (standalone suite + --ab bitwise comparison against baseline gdn_prompt.metal):

  • All gdn_pre outputs (qn, kn, vc, gb, kq, history), gdn_scanr_4 outputs (o, state), and gdn_post outputs (yh, y) pass with 100% bitwise memcmp == 0 across T = 1, 2, 3, 4, 64, 512, 1024, 2048.

3. Paired A/B Timings (Apple M5, 36 GDN Layers, Quiet GPU) #

Token Count T Stage Baseline Median (ms) Candidate Median (ms) Delta (ms) Ratio (cand / base)
512 stage 0 (gdn_pre) 11.563 11.600 +0.037 1.0022
512 stage 1 (gdn_scanr_4) 48.780 47.757 -1.023 0.9791 (-2.09%)
512 stage 2 (gdn_post) 7.423 7.427 +0.004 0.9988
1024 stage 0 (gdn_pre) 23.221 23.175 -0.046 0.9978 (-0.22%)
1024 stage 1 (gdn_scanr_4) 96.569 93.866 -2.703 0.9729 (-2.71%)
1024 stage 2 (gdn_post) 16.501 16.458 -0.043 0.9960
2048 stage 0 (gdn_pre) 46.118 46.262 +0.144 1.0036
2048 stage 1 (gdn_scanr_4) 192.239 187.765 -4.474 0.9764 (-2.36%)
2048 stage 2 (gdn_post) 34.228 34.211 -0.017 0.9995

4. Artifacts #

  • Clean unified diff: /tmp/argon_r20_gdn/argon_r20_gdn.patch (verified with git -C vendor/strata apply --check).
  • Isolated build & test binaries: /tmp/argon_r20_gdn/strata/build-metal/gdn_prompt_parity and /tmp/argon_r20_gdn/strata/build-metal/strata_window_cli.