GPU·

ZYFA FP8 attention on AMD MI355X — power-of-two probability scaling and ping-pong softmax — What does it mean?

The news. On November 5, 2026, researchers at Zyphra published ZYFA, FP8 attention kernels for the AMD Instinct MI355X. On attention inputs captured from real models they reach 1.16–1.76× the throughput of AITER, and 1.99× for DeepSeek-style multi-head latent attention on 32K-token Gaussian benchmarks. Read the paper →

Picture a kitchen with one stove and two cooks. The stove is the matrix pipe, the part of the GPU that multiplies tiles. The prep cook chops, which here means turning attention scores into softmax probabilities on the vector pipe. Switching from BF16 to FP8 doubles the stove's peak speed, but nobody gave the prep cook a faster knife. In FlashAttention the loop for each block of keys is matrix multiply, softmax, matrix multiply, so the stove stays cold whenever the chopping falls behind.

In FP8 the softmax needs about as many vector cycles as the matrix products need matrix cycles, so the two must overlap almost perfectly to keep the matrix unit busy. The paper reports that AITER reaches 39% of peak FP8 matrix throughput at long context, against 49% of peak in BF16. The MI355X adds a second difficulty: unlike NVIDIA Hopper and Blackwell, it does not track completion of matrix instructions in hardware, so the instruction order has to be set by hand in assembly.

Work per wave, per key blockFP8 cyclesBF16 cyclesSource
Two matrix products (matrix pipe)10242048ZYFA Table III
Softmax with exact P: FMA, exponential, convert (vector pipe)896768ZYFA Table III
Softmax with lean P: FMA, integer convert (vector pipe)384not givenZYFA Table III
Standard AttentionHBM (slow)load all ↓write back ↑load all ↓SRAM (fast)
Multiple round trips for all data
Flash AttentionHBM (slow)K₁V₁K₂V₂K₃V₃K₄V₄SRAM (fast)K₁V₁→ compute → next
One tile at a time — click blocks to see ↑
Same result — fewer memory round trips

The first fix is to make the prep cook's job much shorter. A standard FP8 kernel computes the probability with an exponential and then rounds it to FP8. ZYFA instead exploits how the FP8 format is built: the 8-bit pattern of an e4m3 number, read as an integer, is roughly a straight-line function of the base-2 logarithm of its value. That is the same observation behind Schraudolph's fast exponential. So the kernel computes the integer for the probability directly from the score with one multiply-add and one integer conversion, and the result is already the FP8 bit pattern. This is the cook eyeballing the cut instead of weighing each piece.

The price is accuracy. This "lean P" stays within 7.5% of the true probability after rounding, while rounding the exact value is within 5.9%, and it underestimates probabilities that are far below the row maximum. The paper then measures the effect on the model output rather than assuming it is harmless. The saving is large: the vector cycles per block fall from 896 to 384.

The second fix is the ping-pong schedule, a name FlashAttention-3 uses for this alternating arrangement. The two waves on each SIMD take turns: in one phase wave A issues the matrix instructions while wave B computes FP8 probabilities, and in the next phase they swap, with a barrier ending each phase. AITER uses this arrangement too, but its softmax phase runs longer than its matrix phase, so the matrix pipe sits idle for 31.7% of SIMD cycles while one wave waits at the barrier.

With lean P the softmax wave finishes before the matrix wave, so the matrix wave sets the pace of each phase. In the middle of the key loop the matrix pipe is busy for 86% of cycles with lean P, against 60% with exact P. Over the whole loop, including transitions between query tiles, the figures are 78% and 56%.

The third fix protects accuracy. A probability is at most 1 after subtracting the row maximum, so unscaled FP8 probabilities sit in the low part of the format's range, where values lose mantissa bits or round to zero. For every query and block of keys, ZYFA multiplies the block's probabilities by a power of two chosen from the gap between the block maximum and the row maximum, so the block's largest probability gets the code it would have had at the row maximum. The scaled matrix instruction on CDNA4 divides the factor back out as part of the product, so this costs no extra instruction.

The kernel also changes the denominator. If the numerator uses rounded probabilities and the denominator uses the unrounded FP32 sum, every key that underflowed to zero acts like a key with a zero value vector, and the output shrinks toward zero. ZYFA divides by the sum of the same rounded probabilities, so the attention weights still sum to one. It computes that sum with one extra matrix instruction per block, which adds 6% to the matrix cycles per block.

Here is the arithmetic on one wave and one key block, using the cycle counts in the table (measured by the authors for their setup). In BF16 the softmax needs 768 vector cycles against 2048 matrix cycles, which is 37.5% of the matrix time, so overlap does not have to be perfect. Moving to FP8 halves the matrix time to 1024 cycles, and exact P needs 896 vector cycles, which is 87.5% of it. Lean P cuts the vector work to 384 cycles, which is 37.5% again, the same headroom BF16 had. The cook can now finish chopping well before the stove is free.

One caution: the MI355X's sustained clock speed depends on the values being processed. Random Gaussian benchmark inputs therefore do not reliably predict speed on real activations, which is why the headline 1.16–1.76× comes from inputs captured from models and timed at sustained clocks.

Goes deeper in: GPU & CUDA → Tensor Cores & Mixed Precision → Precision Formats

Frequently Asked Questions

Check what you knowMap your AI & GPU knowledge across every track — free, role-based