@@ -126,3 +126,26 @@ Target: D → 5-8 tok/s, then A/B → 20-40 tok/s.
126126- Allocate extra threadgroup memory in FATTN_SMEM
127127- One thread writes 128 floats to threadgroup, barrier, all threads read
128128- This reduces to 1 dequant + 1 barrier per cc iteration instead of 128 broadcasts
129+
130+ ### 2026-03-25: threadgroup memory attempt
131+ - Replaced simd_broadcast with threadgroup memory + simdgroup_barrier
132+ - Thread 0 dequantizes into threadgroup, barrier, all threads read
133+ - ** Result: still 2.4 tok/s**
134+ - Eliminating 31/32 redundant dequant calls had NO effect on speed
135+ - This means the dequant cost itself (even 1× per block) is NOT the bottleneck
136+ - Or the bottleneck is elsewhere entirely (SET_ROWS quantize? block size overhead?)
137+
138+ ### Hypothesis: block size 128 vs 32 causes structural overhead
139+ - q8_0 block size = 32, turbo block size = 128
140+ - The flash attention kernel processes DK4/NL elements per thread per cc iteration
141+ - For q8_0: DK4/NL = 32/8 = 4 iterations (inner ii loop runs 4×)
142+ - For turbo: DK4/NL = 32/32 = 1 iteration (inner ii loop runs 1×)
143+ - But NL = 32 for turbo vs NL = 4 for q8_0 (32/8=4, C=32, NE=1→NW/NE=32 for both)
144+ - Actually NL = NW/NE = 32/1 = 32 for both... so DK4/NL should be the same?
145+ - Wait: for q8_0, nl_k=8 (32 elements / 4 per t4 = 8 chunks). DK4 = 128/4 = 32. DK4/NL = 32/32 = 1.
146+ - So BOTH q8_0 and turbo have DK4/NL = 1 iteration in the inner loop.
147+ - The only difference is the dequant function itself.
148+
149+ ### Next: profile whether the bottleneck is in dequant or elsewhere
150+ - Test with a no-op dequant (return zeros) to measure the kernel overhead
151+ - If still slow → bottleneck is NOT dequant, it's structural
0 commit comments