All posts

Ring Attention: Distributing Million-Token Contexts Across Devices

6 min read distributed-systemstransformersattentionparallel-computing

Ring Attention: Distributing Million-Token Contexts Across Devices

The self-attention mechanism scales quadratically with sequence length — O(n²) in both compute and memory. For a 1M-token context with hidden dimension 4096, the attention matrix alone would consume ~4 TB in FP32. FlashAttention solved the compute-bound case by tiling attention into SRAM-sized blocks, but it still requires the full KV-cache to reside on a single device. Ring Attention breaks this final constraint.

The Memory Wall Problem

Consider a model serving a 1M-token context. Even with FlashAttention's tiled approach, each device must hold:

  • Q block: fits in SRAM (tiled)
  • Full KV-cache: must be accessible for each Q tile

With GQA (grouped-query attention) and 128 KV-heads at dimension 128, a 1M-token KV-cache is:

1,000,000 tokens × 128 heads × 128 dim × 2 (K+V) × 2 bytes (BF16) = ~64 GB

No single accelerator holds this. The naive solution — tensor parallelism — splits the hidden dimension but doesn't reduce the sequence-length memory pressure. Sequence parallelism (Megatron-style) partitions the sequence but requires expensive all-gather operations. Ring Attention offers something better.

The Core Mechanism

Ring Attention arranges N devices in a logical ring. The sequence of length S is partitioned into N contiguous chunks of S/N tokens. Each device i holds:

  • Its local Q chunk: Q_i (S/N tokens)
  • Its local KV chunk: KV_i (S/N tokens), which rotates around the ring

The algorithm proceeds in N steps:

# Pseudocode for Ring Attention on device i
# Each device holds Q_i permanently, KV_j rotates

softmax_running = zeros(S//N, heads)
output_running = zeros(S//N, heads, dim)
max_running = full(S//N, heads, -inf)

kv_local = kv_chunks[i]  # my chunk

for step in range(N):
    # Overlap: send kv_local to next device, receive from previous
    kv_next = async_recv(prev_device)
    async_send(kv_local, next_device)
    
    # Compute: blockwise attention of Q_i against current KV chunk
    attn_block, max_block = flash_attention_block(Q_i, kv_local)
    
    # Online softmax accumulation (numerically stable)
    max_new = maximum(max_running, max_block)
    scale_old = exp(max_running - max_new)
    scale_new = exp(max_block - max_new)
    
    softmax_running = softmax_running * scale_old + scale_new * sum(attn_block)
    output_running = output_running * scale_old + scale_new * attn_block @ V_block
    max_running = max_new
    
    # Wait for communication to complete
    wait(kv_next)
    kv_local = kv_next

# Final normalization
output = output_running / softmax_running

The critical insight: computation and communication overlap perfectly. While device i computes attention against its current KV block, it simultaneously sends that block to device i+1 and receives the next block from device i-1. If compute time ≥ communication time, the ring transfers are completely hidden.

Why This Works: The Arithmetic Intensity Argument

For each ring step, each device computes FlashAttention over blocks of size (S/N × S/N). The compute cost per step is:

FLOPs = 2 × (S/N)² × d × num_heads

The communication per step is sending one KV block:

Bytes = 2 × (S/N) × d × num_heads × sizeof(bf16)

The compute-to-communication ratio:

Ratio = FLOPs / Bytes = (S/N) / sizeof(bf16) = S / (2N)

For S = 1M and N = 8 devices, this ratio is 62,500 — overwhelmingly compute-bound. The ring communication is invisible in the critical path. This arithmetic intensity only improves as sequences get longer, making Ring Attention's efficiency approach 100% for the sequences where it matters most.

Causal Masking: The Asymmetry Problem

Standard self-attention with causal masking means token i only attends to tokens ≤ i. In Ring Attention, when device 3 (holding Q tokens 300K-400K) receives KV from device 5 (tokens 500K-600K), the entire block is masked out — zero useful compute, but communication already happened.

The solution is striped partitioning rather than contiguous. Instead of giving device i tokens [i×S/N, (i+1)×S/N), assign tokens in a round-robin pattern:

Device 0: tokens 0, N, 2N, 3N, ...
Device 1: tokens 1, N+1, 2N+1, 3N+1, ...

With striping, every device pair has approximately equal useful compute — the causal mask distributes evenly. This converts a load-imbalance problem (where later devices do most of the work in the contiguous scheme) into a balanced workload.

An alternative approach preserves contiguous chunks but uses work stealing: devices that finish masked-out blocks early begin processing the next incoming KV block before the current ring step completes.

Composition with FlashAttention

Ring Attention and FlashAttention are orthogonal and composable:

Layer What it tiles Memory saved
FlashAttention Tiles within device SRAM O(n²) → O(n) per device
Ring Attention Tiles across devices O(n) per device → O(n/N) per device

Combined, each device holds O(S/N) KV-cache in HBM and tiles its local FlashAttention computation through SRAM — achieving O(S/N) memory per device with no materialization of full attention matrices anywhere.

Practical Implications: Training vs. Inference

Training: Ring Attention enables gradient computation across million-token sequences. The backward pass follows the same ring pattern in reverse. Memory per device scales as O(S/N) for activations, enabling 1M+ token training on 8-device nodes that would otherwise be limited to ~128K tokens.

Inference (Prefill): For long-document prefill, Ring Attention distributes the quadratic prefill cost across devices. A 1M-token prefill on 8 devices takes approximately 1/8th the time (minus negligible communication overhead).

Inference (Decode): During autoregressive generation, Ring Attention is less beneficial — each step generates one token, so the KV-cache access is O(S) but the compute per step is also O(S). The ring communication overhead becomes proportionally more significant for single-token steps, though it enables serving contexts that simply don't fit on one device.

Comparison with Alternative Approaches

Ulysses (DeepSpeed): Partitions along the head dimension, requiring all-to-all collectives to redistribute between Q and KV projections. Communication cost is O(S×d) per layer — same total bytes as Ring Attention but cannot overlap with compute as effectively because the all-to-all is a prerequisite for computation, not concurrent with it.

Megatron Sequence Parallelism: Uses all-gather on the sequence dimension before attention. Doubles memory during the all-gather and adds synchronization barriers. Ring Attention's point-to-point communication avoids both issues.

Hierarchical approaches (LoongTrain): Combine Ring Attention within a node with Ulysses across nodes, exploiting the higher intra-node bandwidth for the all-to-all pattern while using ring communication for the inter-node path where point-to-point latency dominates.

The Numbers

Reported results from systems implementing Ring Attention show:

  • 1M tokens on 8× A100-80GB: achievable with Ring Attention; impossible without sequence-level distribution
  • Communication overhead: <5% of total step time at 512K+ sequence lengths on NVLink-connected devices
  • Scaling efficiency: >95% weak scaling (doubling devices and sequence length together) up to 64 devices

The key takeaway: beyond ~256K tokens, Ring Attention transitions from "optimization" to "enabler" — these context lengths simply cannot be served without distributing the KV-cache across devices, and Ring Attention does so with minimal overhead.

Looking Forward

Ring Attention is becoming infrastructure rather than research. As context windows push toward 10M+ tokens (multimodal models processing hours of video, entire codebases, or massive document collections), the ring communication pattern will likely be composed with sparse attention patterns — where only a subset of KV blocks need to traverse the ring based on learned routing decisions. The combination of Ring Attention's exact distributed computation with approximate methods (like landmark attention or infinite attention sinks) for the less-critical middle context represents the likely architecture for next-generation long-context systems.