Write the reference before debugging the shader
The Flash Attention 2 path was easier to finish after the algorithm existed in plain JavaScript first. The forward pass used one workgroup per batch, head, and query tile. It walked keys and values in blocks while keeping the online-softmax state in registers. The backward pass recomputed attention from q, k, and a saved log-sum-exp value instead of reading a cached attention matrix. At the…
The Flash Attention 2 algorithm was initially implemented in JavaScript before being translated into shader code. This approach allowed for easier completion of the forward pass, which utilized one workgroup per batch, head, and query tile. The algorithm processed keys and values in blocks while maintaining the online-softmax state in registers.
During the backward pass, the algorithm recomputed attention using q, k, and a saved log-sum-exp value, rather than relying on a cached attention matrix. By removing the cached-matrix traffic at the Mega-class shape, Flash Attention 2 avoided approximately 67 MB of global memory movement per layer per step.
On the Medium preset, the end-to-end comparison showed a significant improvement, moving from 6.8 seconds for WASM SIMD to just 0.7 seconds for WebGPU with the new forward and backward paths. The loss drift remained low at 2.5%. To ensure accuracy, both the forward and backward paths were checked against a naive Node reference implementation before the final WGSL shader implementation was written. This step helped distinguish algorithm errors from shader and integration errors.
Ultimately, the shader code became a translation of established mathematical concepts, rather than the initial point of testing. The complete implementation record can be found at https://posttrainllm.com/devlog.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.