Running AlphaFold3 (single seq mode) 3 times faster on TPUs

Background

Recently I’ve been training some protein design flow matching models on TPUs. To evaluate them protein folding models play an important role. So to keep things simpler (GCP buckets etc), I wanted to use AF3 on TPUs as well. However, the current AF3 codebase didn’t seem to support inference on TPUs.

Correct, we don’t support TPU at the moment.

— GitHub issue #550 [1], October 2025

Running AF3 with XLA

Unsupported doesn’t mean we cannot run it on TPUs.

AF3 is written in JAX and it compiles through XLA, which runs natively on TPUs. So what’s the issue? For TPUs it does not have an optimized kernel for pair-biased attention.33 AF3 actually has four pair-biased attentions: triangle attention, the single attention in the pairformer, the diffusion transformer and the atom transformers. Only triangle attention goes through tokamax. Because of this, when you run AF3 on a v6e chip it runs slow even compared to a 5090 44 This is mostly not the attention’s fault: one unfused triangle-attention call takes 0.71 ms against 0.32 ms fused, which over the 1,056 calls in a fold adds about 0.4 s, while the TPU VM’s slower CPU costs about 1.1 s..

To dig a little deeper: AF3 calls tokamax, an OpenXLA library of fused JAX kernels, and --flash_attention_implementation picks which tokamax backend runs.

However, on a TPU we hit two dead ends:

  1. tokamax’s fused GPU kernels (triton, the default, and cudnn) don’t run on TPUs.
  2. tokamax’s TPU kernel (mosaic) doesn’t accept an attention bias at all 55 The check is in pallas_mosaic_tpu_common.py [3]: passing any bias raises this error – still the case in tokamax 0.0.17, and AF3′s triangle attention needs one: the pair bias.
Figure 1: Why AF3 has no fast attention path on a TPU. AF3 hands its pair-biased triangle attention to tokamax. tokamax’s fused GPU kernels don’t run on TPUs, and its TPU kernel doesn’t accept a bias, which leaves the plain-XLA path: it runs anywhere, but unfused.

If we don’t care about performance, we can just run the standard AF3 inference code with this flag 66 Defined in run_alphafold.py [4], whose help text calls xla “no flash attention” and “portable across GPU devices”; TPUs aren’t mentioned..

--flash_attention_implementation=xla

With it, AF3 computes attention with ordinary JAX operations instead of a hand-written GPU kernel. XLA compiles those for the TPU like the rest of AF3′s JAX code. But since this automatic compilation doesn’t result in a fused kernel, it writes the full attention-logit tensor to memory and reads it back 77 Flash attention (Dao et al., 2022 [5]) computes softmax(QKᵀ + bias)·V in tiles held in fast on-chip memory, keeping a running maximum and sum for the softmax, so the N × N matrix of logits is never written to the slower main memory (HBM). That removes the largest memory traffic in attention. The TPU kernel later in this post uses the same idea in a simpler form: at these sizes a whole row of logits fits on-chip, so it never has to tile across keys.. How much does this hurt us?

Optimizations in a nutshell

If we look at the timing for a full end to end run on a v6e chip, it runs in about 5.8 seconds. For context I measured this on a 5090 as well.

featurization (host CPU)rest of the fold, XLA attentionrest of the fold, fused Triton attention
TPU v6e
XLA attention
1.85
3.96
5.81 s
TPU v6e
pipelining + hoisting
3.56 s
TPU v6e
+ Pallas kernels
2.77 s
TPU v6e
+ tighter padding
1.81 s
RTX 5090
Triton (default)
0.77
4.56
5.33 s
RTX 5090
XLA attention
0.77
5.33
6.10 s
RTX 5090
pipelining + hoisting
4.32 s
RTX 5090
+ tighter padding
3.11 s
Figure 2: End to end folding time for a 180-residue designed protein with two ligands at AF3′s standard settings (5 diffusion samples, 10 recycles, 200 denoising steps, no MSA). Each bar is the median of 10 folds (2 designs × 5 seeds), compilation excluded.

How much do precision errors propagate?

Here are all the optimizations in one place, with what each one does to AF3′s predictions. Two of them just reorganize when and where the work happens, so the outputs stay the same as the original AF3 inference code’s.

The other four change the floating-point arithmetic. The kernels round the same way as AF3′s own code on more than 99% of values, but through 200 denoising steps even that can change the final structure.

ChangeWhat it doesTime per foldOutputs vs stock AF3
Pipelined driverfeaturizes the next inputs on the CPU while the TPU runs the current one5.81 → 3.80 sidentical, bit for bit
Hoistingcomputes the diffusion head’s position-independent work once per fold, not at each of the 200 steps→ 3.56 sidentical, bit for bit
Pallas triangle attentionfused attention that keeps the logits on-chip→ 3.21 srounding: 99.996% of values identical*
Pallas transitionLayerNorm, SwiGLU and output projection in one kernel→ 3.08 srounding: 99.97% identical
Pallas triangle multiplicationfused triangle multiplication→ 2.77 srounding: 99.2–99.6% identical
Tighter paddingpads to the next multiple of 16 tokens (192 here) instead of 256→ 1.81 srounding, plus new starting noise for 4 of the 5 diffusion samples
Table 1: Every change in this post, in the order it is applied, with the warm time per fold after it (the bench and settings of the timing figure above). “Identical” means every raw output of the model, all 5 diffusion samples included, matches stock AF3 bit for bit on all 10 bench folds. For the kernels: the share of a layer’s output values that match AF3′s own layer exactly, on real model inputs and weights. *For the attention computation itself. Over the whole attention layer, 53–73% of values are identical: once attention is a separate kernel, XLA fuses the projections around it differently. The error against a float32 reference is the same as stock AF3′s.

Do the predictions change?

Pipelining and hoisting cannot change anything: the outputs are bit for bit identical. The kernels can, through rounding, so I checked them in two ways.

First, against real structures. I folded 40 proteins from the PDB from their deposited sequences (with their ligands, no MSA), once with stock AF3 and once with the kernels, with the same padding and seed, and scored each prediction against the deposited structure: lDDT over all the protein’s heavy atoms, where 1 is a perfect match. If the kernels changed accuracy, the points below would move off the diagonal. For scale, the other two panels make changes that have nothing to do with the kernels: a new random seed, and running stock AF3 on an RTX 5090 instead of the TPU.

AF3′s confidence in the before structure (mean pLDDT):very high (≥ 90)confident (70–90)low (50–70)very low (< 50)
Pallas kernels
TPU v6e, same seed
with the kernels
0.20.20.40.40.60.60.80.8mean change −0.002
typical change 0.027
stock AF3
New random seed
stock AF3, RTX 5090
seed 231
0.20.20.40.40.60.60.80.8mean change +0.001
typical change 0.015
seed 230
Other hardware
stock AF3, same seed
TPU v6e
0.20.20.40.40.60.60.80.8mean change +0.008
typical change 0.025
RTX 5090
Figure 3: Accuracy before (x) and after (y) a change, one dot per PDB protein: all-atom lDDT (protein heavy atoms) of AF3′s top-ranked structure against the deposited structure (1 = perfect). Points on the diagonal did not change. Colours show how confident AF3 itself was about the before structure (mean pLDDT, in AlphaFold’s colour bands); a confident colour on a low lDDT means AF3 was sure of a structure that does not match the deposited one. “Mean change” is the average of after − before; “typical change” the average size of the change. AF3-LA weights, single-sequence (no MSA), 5 diffusion samples, 10 recycles, 200 denoising steps.

The kernels don’t shift accuracy: the mean change is −0.002 lDDT. Individual proteins do move, by 0.027 on average, about as much as running stock AF3 on an RTX 5090 instead of the TPU (0.025) and a bit more than a new random seed (0.015). Single-sequence AF3 is unsure about most natural proteins (mean pLDDT around 50, and most points sit low on both axes), and for an unsure prediction any small numerical difference, ours, a new seed or another chip, sends the diffusion somewhere slightly different.

Second, on the inputs I actually fold: 40 designed proteins with ligands, where AF3 is mostly confident. There is no deposited structure, so I compared top-ranked structures directly, over three seeds. With the kernels they move a median of 0.52 Å from stock AF3′s, against 1.29 Å for changing the seed, and the confident ones (pLDDT of 90 or more) move at most 0.84 Å.

Related implementations

After I worked on this with claude + codex on optimizing AF3 for TPUs, I realized that I didn’t do much of a existing literature search. So we revisited Anthropic’s FlashPairformer code [6] that include three close comparisons, all targeting GPUs through Pallas’s Triton backend:

However, Anthropic’s repo mainly targets NVIDIA GPUs through the Pallas kernels. With only their compiler settings switched to TPU ones, the triangle-attention and triangle-multiplication kernels do not compile on a TPU: their memory layouts break the TPU’s block-shape rules.

Apart from Anthropic’s repo, JAX’s own Pallas FlashAttention for TPUs [2] does accept an additive attention bias, but only as a separate copy for every row. On AF3′s triangle attention it is 1.6–4.4× slower than the kernel in this post (at 256 tokens 0.54 ms for the kernel alone and 0.84 ms with the bias copy and transposes it needs, against 0.32 ms), and no faster than plain XLA up to 384 tokens. Most of the gap is its handling of AF3′s 32-wide heads; building the per-row bias costs the rest. Separately, JAXBench: Benchmarking Autonomous TPU Kernel Optimization [7] includes an AlphaFold2-style triangle-multiplication workload in its TPU v6e benchmark; its reference workload [8] differs from the exact AF3 module.

References

  1. AlphaFold 3 contributors (2025). “AlphaFold 3 TPU support discussion: GitHub issue 550.”
  2. The JAX Authors (n.d.). “JAX Pallas TPU FlashAttention implementation.”
  3. OpenXLA contributors (n.d.). “Tokamax: Pallas Mosaic TPU attention input-support checks.”
  4. Google DeepMind (n.d.). “AlphaFold 3 inference runner: flash-attention implementation flag.”
  5. Dao et al. (2022). “FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness.”
  6. Anthropic (n.d.). “FlashPairformer: Pallas kernels for biomolecular modeling on GPUs.”
  7. Tschand et al. (2026). “JAXBench: Benchmarking Autonomous TPU Kernel Optimization.”
  8. JAXBench contributors (n.d.). “JAXBench: AlphaFold2-style triangle-multiplication reference workload.”
KUDOSDon’t
Move
Thanks!