round 9 track b: table-free barriers + isolated down timing #

deliverable #

  • patch: /tmp/sol_r9_moemm/sol_r9_moemm.patch
  • scratch: /tmp/sol_r9_moemm/strata
  • verified git -C vendor/strata apply --check /tmp/sol_r9_moemm/sol_r9_moemm.patch: exit 0.
  • touches only metal/kernels/moe_mm.metal and metal/tests/moe_mm_parity.cpp; no tracked vendor files modified.

important premise correction #

the copied baseline already has W8<T_Q6_K>, at lines 810–830. it shares scale/address work and loads each 4-byte run through two ushorts (the 210-byte block stride is only 2-aligned). the patch does not add a duplicate specialization or claim its existing benefit. source snapshots and sha256s are in /tmp/sol_r9_moemm/baseline and manifest.json.

kept #

  • in mm_gu3 and mm_down3, call load_tab and its threadgroup barrier only when fmt<F>::TAB > 1. table-backed formats retain both; no other barriers change.
  • --dn-bench times the down dispatch, analogous to --gu-bench.
  • isolated gu/down benchmarks run one complete untimed pipeline first, so XS/HS contain real deterministic inputs rather than uninitialized allocations.
  • isolated benchmarks use one 512-expert weight set, four dispatches/sample, three samples, and 0.1 s warmup. ordinary --bench remains four rotated sets, eight dispatches, five samples, 0.3 s warmup. this bounds the standalone budget; absolute numbers are not directly comparable to the old isolated evaluator.

method and limits #

apple m5, safe metal math, deterministic harness random inputs. gu: Q6_K/Q2_0, --v3 --tile 16,16,32,4 --dtile 64,32,2; down: IQ2_XS/Q2_0, --v3 --tile 16,32,32,4 --dtile 64,32,2. T=512/1024/2048. three interleaved baseline/candidate pairs, each measurement the median of three batches of four dispatches. COOP_K4=1 after the original probe confirmed runs of four, avoiding the extra layout-probe compilation on this m5. no live server requests, full-model runs, or GPU-parallel jobs.

all executable invocations had a 5 s kill deadline. the original four-layer isolated evaluator hit that deadline for q6 T2048. the adjusted evaluator's warm successful invocations were ~0.3–1.0 s; cold MSL/pipeline compilation sometimes cost 4–5 s and several exploratory/final reruns hit the deadline (no result counted). thus the requested <2 s wall target is achieved warm, not guaranteed cold. dumps warm were ~0.1–0.2 s, not reliably <0.1 s. no timeout was treated as a passing test. raw failure records remain in runs.json. the final harness-only cleanup renamed a repeated condition to isolated_bench; rebuild passed, but its redundant final dump rerun encountered a cold compile timeout. kernel parity below was completed earlier on the exact delivered kernel bytes.

paired results #

median dispatch time in us; lower is better. all three pairs retained, including a large transient T512 timing disturbance (gu barrier 35898.5 us, down barrier 28773.8 us). no outlier filtering. full samples in summary.json.

dispatch T baseline barrier guard change
q6 gate/up 512 15331.2 15289.4 -0.27%
q6 gate/up 1024 22569.4 22468.7 -0.45%
q6 gate/up 2048 36421.2 36328.8 -0.25%
q2 down 512 3489.4 3485.3 -0.12%
q2 down 1024 5143.8 5130.3 -0.26%
q2 down 2048 8656.1 8585.8 -0.81%

these are small/noise-scale changes, not a convincing performance win against the predeclared >3% criterion. retain the guards as a small removal of unnecessary synchronization with bitwise parity, not a meaningful prefill-speed claim. no end-to-end estimate established.

rejected / not promoted #

  • q6 byte-load specialization (same shared fields): bitwise identical. exploratory T2048 39739 us versus baseline 36264, and T512 15464 versus bracketed baseline 15233/15314. no improvement; larger follow-up runs timed out in cold compilation. not included.
  • q6 rd32 helper replacement: rd32 already performs the same two-ushort reconstruction as baseline. bitwise identical on Q6_K; exploratory T2048 39327 versus baseline 36264, T512 15335 versus bracketed baseline 15233/15314. no established win; not included. IQ3_S control dump for this rejected variant timed out, so no blanket four-format claim for this variant.
  • W8<Q2_0> shared scale, atop barrier guard: down medians 3481.6 / 5131.7 / 8587.0 us at T512/1024/2048, versus barrier-only 3485.3 / 5130.3 / 8585.8. no added benefit; not included. all four gu-format controls passed dump identity for this exploratory variant.
  • W8<Q4_K>/W8<Q5_K> already exist; left unchanged.

correctness / review #

  • scratch CMake/Ninja build of moe_mm_parity: exit 0. only preexisting fastMathEnabled deprecation warning.
  • final barrier-only kernel vs copied baseline: HS+y dumps 100% byte-identical at T256 for Q6_K, Q2_0, IQ2_XS, IQ3_S gate/up, each with Q2_0 down; actual dump byte equality (memcmp == 0 equivalent), not an L2 tolerance. parity.json records the four final-kernel comparisons plus exploratory comparisons.
  • no CPU-reference run: intentionally used the requested short dump A/B path.
  • reviewed complete scratch view_diff, then view_code for benchmark context; replaced repeated isolated-mode condition with one boolean. no debug output remains.

reproduction / evidence #

cmake -S /tmp/sol_r9_moemm/strata/metal -B /tmp/sol_r9_moemm/build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build /tmp/sol_r9_moemm/build --target moe_mm_parity -j 4
COOP_K4=1 STRATA_METAL_KERNELS=/tmp/sol_r9_moemm/k_base /tmp/sol_r9_moemm/build/moe_mm_parity --v3 --gu Q6_K --dn Q2_0 --tile 16,16,32,4 --dtile 64,32,2 --T 2048 --gu-bench
COOP_K4=1 STRATA_METAL_KERNELS=/tmp/sol_r9_moemm/k_barrier /tmp/sol_r9_moemm/build/moe_mm_parity --v3 --gu IQ2_XS --dn Q2_0 --tile 16,32,32,4 --dtile 64,32,2 --T 2048 --dn-bench

swap k_base/k_barrier for each A/B command; same binary/evaluator for both. use a 5 s external deadline as in the recorded run wrapper. runs.json contains exact args, source variant, exit codes, durations, stdout, and failed attempts; summary.json, parity.json, and manifest.json capture summarized measurements, comparisons, and source hashes. all kernel variants remain in k_*; plan.md records the initial contract.