FlashAttention Implementation › CUDA Kernel Basics
Language AI HandbookAll chapters FlashAttention Implementation › CUDA Kernel BasicsOne section · Sections in this chapter3 / 10 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
FlashAttention is implemented as a custom CUDA kernel, meaning it runs directly on GPU hardware with fine-grained control over memory access. Understanding a few CUDA concepts helps appreciate what FlashAttention does under the hood.
A CUDA kernel is a function that runs on the GPU across many parallel threads. Threads are organized into blocks, and blocks are organized into a grid. Each thread can access different levels of memory: registers (private to the thread), shared memory (shared within a block), and global memory (HBM, accessible by all threads).
Thread Organization
CUDA organizes computation into a hierarchy. At the lowest level, individual threads execute the same code on different data. Threads are grouped into blocks, typically containing 256-1024 threads. All threads in a block can communicate through shared memory and synchronize their execution. Blocks are grouped into a grid that covers the entire problem.
For attention, a natural mapping assigns one block to compute attention for one query block against all key-value blocks. Within a block, threads collaborate to load data into shared memory, compute dot products, and accumulate results.

Memory Access Patterns
The key to GPU performance is coalesced memory access. When threads in a warp (a group of 32 threads that execute in lockstep) access consecutive memory addresses, the hardware combines these into a single efficient transaction. When threads access scattered addresses, each access becomes a separate transaction, significantly slowing execution.
FlashAttention carefully structures its memory access to achieve coalescing. When loading a block of K from HBM, consecutive threads load consecutive elements. When writing results, the same pattern applies. This attention to memory layout is one reason FlashAttention achieves such high hardware utilization.
def demonstrate_memory_access_patterns():
"""
Illustrate the difference between coalesced and strided memory access.
"""
patterns = {
"coalesced": {
"description": "Thread i accesses address i",
"transactions": 1,
"effective_bandwidth": "100%",
},
"strided_2": {
"description": "Thread i accesses address 2*i",
"transactions": 2,
"effective_bandwidth": "50%",
},
"random": {
"description": "Thread i accesses random address",
"transactions": 32,
"effective_bandwidth": "3%",
},
}
return patterns
patterns = demonstrate_memory_access_patterns()Memory Access Patterns (32-thread warp, 4-byte elements): Pattern Transactions Effective BW ----------------------------------------------- coalesced 1 100% strided_2 2 50% random 32 3% FlashAttention uses coalesced access patterns throughout.
