← all posts
AI 2026.05.03 · 10 min read Advanced

Long Context LLM — 두 개의 완전히 다른 문제

Prefill의 O(L²) 계산 폭발과 Decode의 KV 메모리 누적이 왜 별개의 병목인지, StreamingLLM·YaRN·Ring Attention이 각각 어느 문제를 해결하는지 추적한다.


“Long context inference가 느리다”는 말은 하나의 문제처럼 들린다. 실제로는 완전히 성격이 다른 두 병목이 공존한다. 이 구분을 이해하지 못하면, StreamingLLM·YaRN·Ring Attention이 각각 왜 다른 기법인지도, 왜 셋 다 필요한지도 설명할 수 없다. 어떤 병목이 어디서 발생하는가?

Prefill vs Decode — 정반대의 계산 특성

Prefill(프롬프트 처리)과 Decode(토큰 생성)는 계산 프로파일이 정반대다.

Prefill에서는 길이 LL의 프롬프트 안에서 모든 Query가 모든 Key/Value와 attend한다. Attention 행렬의 크기는 L×LL \times L이므로 계산량은 다음과 같다.

Prefill FLOPsL2×dtotal\text{Prefill FLOPs} \approx L^2 \times d_{\text{total}}

LLaMA-70B(dtotal=8192d_{\text{total}}=8192), L=128KL=128\text{K}를 대입하면 약 1.3×10151.3 \times 10^{15} FLOPs. A100 기준 이론적 하한이 4초를 넘는다. Prefill의 병목은 compute다.

Decode에서는 매 스텝마다 새로운 Query 1개가 누적된 LL개의 Key/Value와 attend한다. 계산량 자체는 O(L)O(L)로 작지만, 모든 이전 토큰의 K/V를 GPU 메모리에 유지해야 한다.

MKV=B×2×L×dtotal×dtype_bytesM_{\text{KV}} = B \times 2 \times L \times d_{\text{total}} \times \text{dtype\_bytes}

L=128KL=128\text{K}, 배치 8, BF16이면 약 26 GB. A100 80GB에서 배치 2–3이 한계에 도달한다. Decode의 병목은 memory다.

두 병목의 직교성

Prefill 가속(Flash Attention 등)은 KV 메모리에 영향을 주지 않는다. KV 절감(GQA, 양자화 등)은 Prefill FLOPs에 영향을 주지 않는다. 따라서 두 문제는 각각 다른 기법으로 해결해야 한다.

StreamingLLM — Decode 메모리를 상수로

Decode 메모리를 줄이는 가장 단순한 접근은 슬라이딩 윈도우다 — 최근 WW개 토큰만 KV cache에 유지하면 메모리가 O(W)O(W)로 고정된다. 그런데 Xiao et al.(2024)의 관찰에 따르면, 이것만으로는 perplexity가 10배 이상 급등한다.

이유는 Softmax normalization에 있다. 초기 토큰들은 실제 내용과 무관하게 모든 Query에 대해 비정상적으로 높은 attention weight를 받는 “attention sink” 역할을 한다. 이 토큰들이 윈도우 밖으로 밀려나면 Softmax의 분모(partition function)가 불안정해진다.

Keff=K[1:M]K[tW:t],Keff=M+W=constK_{\text{eff}} = K_{[1:M]} \cup K_{[t-W:t]}, \quad |K_{\text{eff}}| = M + W = \text{const}

처음 MM개(4–8개)를 sink로 고정하고 최근 WW개를 유지하면 KV cache가 상수가 된다. t=100Kt = 100\text{K}에서도 메모리는 (M+W)×d(M+W) \times d뿐이다.

YaRN — 학습 범위 밖의 Position을 보간

LLaMA처럼 4K context로 학습된 모델을 128K로 확장하려면 RoPE의 position 범위를 늘려야 한다. 단순 외삽(extrapolation)은 m>4Km > 4\text{K}에서 high-frequency 성분이 aliasing을 일으켜 perplexity가 약 32배 폭등한다.

Chen et al.(2023)의 Position Interpolation은 모든 position을 균일하게 스케일한다.

m=m×LtrainLinferm' = m \times \frac{L_{\text{train}}}{L_{\text{infer}}}

이 방식은 low-frequency(장거리) 성분에는 적합하지만, high-frequency(세밀한 위치 구분)를 과도하게 압축해 정보를 손실한다.

YaRN(Peng 2024)은 dimension별로 다른 보간 계수를 적용한다.

θiYaRN=λ(θi)θi,λ(θ)={1high-freqramp()transitionslow-freq\theta_i^{\text{YaRN}} = \lambda(\theta_i) \cdot \theta_i, \quad \lambda(\theta) = \begin{cases} 1 & \text{high-freq} \\ \text{ramp}(\cdot) & \text{transition} \\ s & \text{low-freq} \end{cases}

High-frequency dimension은 λ=1\lambda=1로 학습 당시 그대로 유지하고, low-frequency만 스케일 s=Ltrain/Linfers = L_{\text{train}}/L_{\text{infer}}로 내린다. 결과적으로 4K → 128K 확장 시 perplexity 손실이 2% 미만이며, fine-tuning 없이 즉시 적용 가능하다.

트레이드오프

YaRN은 추가 학습 없이 context를 확장하지만 여전히 extrapolation이다. 10M+ 극단적 길이에서는 불안정해질 수 있으며, fine-tuning을 병행하면 더 견고해진다. 또한 RoPE 기반 모델에만 적용 가능하다.

Ring Attention — Prefill을 분산으로

YaRN으로 128K까지 확장해도, L=1ML=1\text{M}에서의 Prefill은 단일 GPU로 불가능하다. Attention 행렬 QKTRL×LQK^T \in \mathbb{R}^{L \times L}이 BF16 기준 2 TB를 요구하기 때문이다.

Ring Attention(Liu 2024)은 NN개 GPU에 sequence를 분할한다.

정리 1 · Ring Attention Memory Reduction

NN개 GPU에서 Ring Attention을 적용하면 GPU당 attention 행렬 메모리는 단일 GPU 대비 N2N^2배 감소한다.

▷ 증명

각 GPU는 L/NL/N개 Query를 고정으로 보유한다. NN라운드에 걸쳐 K/V chunk L/NL/N개씩 링으로 순환하며, GPU당 attention 행렬 크기는 (L/N)×(L/N)(L/N) \times (L/N)이 된다. 따라서 per-device memory는 L2d/N2L^2 d / N^2이고, 단일 GPU의 L2dL^2 d 대비 N2N^2배 감소한다. \square

N=16N=16이면 2 TB → 8 GB 수준으로, A100에서 현실적이다. 통신량은 라운드당 (L/N)×d(L/N) \times d bytes로 computation과 pipelining하면 대부분의 overhead를 숨길 수 있다.

Ring Attention은 단일 GPU inference에서는 의미가 없다. 대규모 분산 학습 클러스터에서 1M context 모델을 훈련·추론할 때 사용하는 기법이다.

정리

  • Long context 병목은 Prefill(compute)Decode(memory) 두 개로, 각각 다른 해결책이 필요하다.
  • StreamingLLM은 attention sink + 슬라이딩 윈도우로 Decode KV 메모리를 O(1)O(1) 로 만든다. 단, 장거리 정보는 잃는다.
  • YaRN은 dimension별 RoPE 보간으로 fine-tuning 없이 context를 128K까지 확장한다.
  • Ring Attention은 sequence를 GPU간 분산해 Prefill의 O(L2/N2)O(L^2/N^2) 메모리를 가능하게 하며, 1M context 모델의 토대가 된다.

세 기법은 경쟁이 아니라 서로 다른 축을 다룬다. 실제 1M context 시스템에서는 셋 모두 동시에 쓰인다.