Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 74

FlashAttention: Tiling and Online Softmax

Recommended resources

Introduction

In our last lesson, we deconstructed the standard self-attention mechanism and identified its Achilles' heel: the materialization of the enormous attention matrix. You learned how this leads to quadratic memory complexity and creates a severe I/O bottleneck, as the GPU is forced to shuttle this massive intermediate result to and from slow global memory (HBM). This makes the algorithm fundamentally memory-bound, limiting the context length of even the most powerful Transformer models.

Now that we have a firm grasp of the problem, this lesson introduces the elegant solution. We will dive into the two core algorithmic innovations that allow FlashAttention to compute the exact same result, but with far greater efficiency: tiling and online softmax. You'll see how these concepts combine to create a single-pass, I/O-aware algorithm that avoids the main bottleneck entirely, paving the way for models with dramatically longer sequence lengths.


Tiling and the Challenge of Softmax

From your experience optimizing GEMM, you are already well-acquainted with the power of tiling. By partitioning large matrices into smaller blocks that fit into fast on-chip SRAM, we can drastically reduce the number of costly trips to global memory and maximize data reuse.

However, a naive application of tiling fails for self-attention. The computation C = A B can be tiled because matrix multiplication is based on addition, which is associative. The sum of block-wise products is the same as the product of the full matrices.

The attention formula, however, contains a softmax operation:

Softmax is not associative. The value of softmax(x_i) depends on every other element in its row, as it requires a global denominator . You cannot simply compute softmax on one tile of and then combine it with the softmax of another tile to get the correct result. This dependency seems to force us to compute the entire matrix before we can proceed, which is precisely the problem we want to avoid.

The following video provides a refresher on how tiling benefits I/O-bound algorithms and sets up the challenge that softmax presents.

How FlashAttention Accelerates Generative AI Revolution

This video from Jia-Bin Huang's channel, "How FlashAttention Accelerates Generative AI Revolution," clearly visualizes the concepts we'll discuss.

First, watch the segment on tiling for matrix multiplication as a review of I/O-aware algorithms. Then, continue to the section that introduces the softmax problem, which highlights why it is not directly amenable to simple tiling.

The central question, then, is: how can we reformulate the softmax calculation to work in a block-wise, or "online," fashion?


The Online Softmax Trick

The breakthrough that enables FlashAttention is a method to compute softmax in a streaming manner, updating the result as we process blocks of the input one by one. This is often called "online softmax" or using an "online normalizer."

Let's break down how it works. Recall the "safe softmax" trick from our previous module, where we subtract the maximum value for numerical stability:

A standard implementation does this in three passes: one to find , a second to find the denominator , and a third to compute the final values. This involves multiple reads of the input data from HBM.

The online approach merges these passes. Imagine processing the input vector in blocks. As we process a new block, we can update our running statistics—the current maximum value and the denominator sum—from the previous blocks.

Let's say we have processed some blocks and have a running maximum and a running denominator sum . When a new block arrives, we find its local maximum, . The new overall maximum is .

If is different from , our previous sum is now incorrect because it was normalized with the wrong maximum! The key insight is that we can correct it. We can "rescale" the old denominator by multiplying it by and then add the contribution from the new block.

The update rule looks like this:

where is the sum for the current block, computed using . This allows us to compute the correct final denominator by iterating through the data just once.

The following resource provides a fantastic mathematical intuition and a numerical walkthrough of this exact process.

ELI5 FlashAttention Algorithm and Online Normalizer Calculation for Softmax (NVIDIA Paper) - part 3

This video by Sachin Kalsi, "ELI5 FlashAttention Algorithm and Online Normalizer," gives an exceptionally clear explanation of the math behind the online normalizer.

First, watch the segment explaining the core intuition of the online normalizer calculation. The example at 24:14 showing how to "undo" the old normalization is the most critical part. Next, watch the numerical example that follows. This will make the abstract formulas concrete by showing how the running maximum (M) and denominator (D) are updated step-by-step.


From Online Softmax to Fused Tiled Attention

The online softmax trick allows us to compute the denominator in a single pass. FlashAttention takes this one step further. Instead of just computing the attention matrix , it fuses the final multiplication with the matrix directly into the same loop.

To do this, we introduce a third running statistic: the output vector, . The update rule for the output vector is similar in spirit to the denominator update. The previously computed output is rescaled to account for the new maximum, and the contribution from the current block is added.

The full, single-pass tiled algorithm can be summarized as:

  1. Initialize running statistics: , , .
  2. Loop through blocks of and :
    a. Load a block of , , and into fast SRAM.
    b. Compute the dot product for that block: .
    c. Find the new overall maximum, .
    d. Update the running statistics and using the rescaling trick.
  3. After the loop, perform a final normalization of .

This entire process is visualized in the diagram below, which should now be much clearer. The "Outer Loop" corresponds to iterating through the tiles of and , and the "Inner Loop" iterates through tiles of . Inside the "Compute Block", the online update of our running statistics takes place.

This diagram illustrates the tiled computation of FlashAttention. The Outer Loop iterates over key-value blocks, and the Inner Loop over query blocks. All computation happens on-chip in SRAM, updating running statistics. The large NxN attention matrix is never written to HBM, avoiding the I/O bottleneck.

To solidify your understanding, the next resource provides an exceptional, step-by-step manual calculation. It takes a small example and processes it tile-by-tile, showing exactly how the running statistics are updated, perfectly matching the algorithm.

FlashAttention by hand - DEV Community

This article by Lewis Won on DEV Community provides a clear, numerical walkthrough that makes the abstract algorithm concrete. It's based on the formal derivation in the "From Online Softmax to FlashAttention" lecture notes.

First, read the section Conceptual Overview to set the stage. Then, meticulously follow the main walkthrough in the section FlashAttention by hand. Trace the updates to m_running, d_running, and o_running as the algorithm processes Tile 1 and Tile 2. Pay close attention to the rescaling step. Finally, read the section Walkthrough of the diagram and the "Putting it all Together" subsection that follows, which maps the manual calculation directly to the diagram we just saw. You should also read Appendix B, which clarifies a subtle but important detail about when the final normalization occurs.

The data flow within a Streaming Multiprocessor (SM) during this process is highly orchestrated. Different groups of threads (warps) are assigned specific tasks: some load data from HBM to shared memory, MMA warps perform the matrix multiplications, and other warps handle the online softmax and correction calculations before the final result is written out.

This diagram shows the data flow for a single tile within a Streaming Multiprocessor. "Load Warps" fetch tiles of Q, K, and V from global memory into shared memory. "MMA Warps" perform the matrix multiplications. "Softmax Warps" and "Correction Warps" apply the online update rules. Finally, an "Epilogue Warp" writes the updated output tile back to global memory.

Conclusion

In this lesson, we have demystified the core mechanisms of FlashAttention. You have moved from understanding why standard attention is slow to understanding how FlashAttention fixes it without any approximation.

Key Takeaways:

  • Tiling: The input matrices are processed in blocks that fit into fast on-chip SRAM, minimizing slow global memory access.
  • Online Softmax: This is the key algorithmic trick. By maintaining and updating running statistics (), we can compute the exact, numerically stable softmax and attention output in a single pass over the tiles.
  • Kernel Fusion: The matrix multiplications and the softmax calculation are fused into a single GPU kernel. This avoids writing the massive intermediate attention matrix to global memory, thereby breaking the quadratic memory bottleneck and solving the I/O problem.

You are now equipped with the conceptual foundation of one of the most important algorithms in modern AI systems. The next logical step is to translate this understanding into code.

In our next lesson, you will begin implementing a simplified FlashAttention kernel. We will start with the inner loop, focusing on computing the output for a single block and correctly updating the running statistics, bringing the theory you learned today one step closer to practical, high-performance execution on the GPU.