Native Sparse Attention (DeepSeek NSA)

64k 토큰 길이에서는 어텐션(attention)이 디코딩 지연(decode latency)의 70~80%를 차지합니다. 모든 오픈 모델 연구소가 이를 개선할 계획을 갖고 있고, 그중 실제로 자리를 잡은 접근이 DeepSeek의 NSA(ACL 2025 Best Paper)입니다. NSA는 세 개의 병렬 어텐션 가지(branch)를 사용합니다. 즉, 압축된 거친 단위(coarse-grained) 토큰, 선택적으로 보존한 세밀한 단위(fine-grained) 토큰, 국소 문맥(local context)을 위한 슬라이딩 윈도우(sliding window)를 학습된 게이트(gate)로 결합합니다. 또한 하드웨어 정렬(hardware-aligned), 즉 커널 친화적(kernel-friendly)이며, 추론 시점에 덧붙이는 장치가 아니라 사전 학습(pre-training)에서 그대로 동작하도록 본질적으로 학습 가능(natively trainable)합니다. 64k 디코딩에서는 풀 어텐션(full attention) 품질을 맞추거나 넘으면서 FlashAttention보다 빠르게 실행됩니다. 이 강의에서는 세 가지를 처음부터 끝까지(end-to-end) 만들어 보고, 희소성(sparsity)이 왜 전체 미분 가능(end-to-end differentiable)한지 확인합니다.

유형: Build 언어: Python (표준 라이브러리) 선수 지식: Phase 7 · 12 (KV cache, FlashAttention), Phase 7 · 15 (attention variants), Phase 10 · 16 (differential attention) 예상 시간: 약 60분

학습 목표

  • NSA의 세 어텐션 가지(branch)를 나열하고, 각각이 무엇을 포착하는지 설명합니다.
  • 이전 희소 어텐션(sparse attention) 방법들이 추론 전용(inference-only)이었던 것과 달리, NSA가 왜 "본질적으로 학습 가능(natively trainable)"한지 설명합니다.
  • 64k 문맥에서 풀 어텐션 대비 NSA가 절약하는 어텐션 연산량(compute savings)을 압축 블록 크기(compression block size)와 선택 top-k의 함수로 계산합니다.
  • 짧은 합성 시퀀스(synthetic sequence)에서 표준 라이브러리 Python으로 세 가지를 결합해 구현하고, 게이트 가중치(gate weight)가 합리적으로 동작하는지 확인합니다.

문제

시퀀스 길이가 N일 때 풀 어텐션은 시간 복잡도 O(N^2)와 레이어당 O(N) 크기의 KV 캐시(cache)를 요구합니다. 64k 토큰 길이에서는 연산량과 메모리 대역폭(memory bandwidth) 수치가 치명적인 수준이 됩니다. NSA 논문이 제시하는 이론적 측정 추정치에 따르면 64k에서는 전체 디코딩 지연의 70~80%를 어텐션이 차지합니다. 그 뒤에 따라오는 모든 지표, 즉 첫 토큰 응답 시간(Time To First Token; TTFT), 초당 토큰 수(tokens/sec), 백만 토큰당 비용은 모두 어텐션 비용에 좌우됩니다.

희소 어텐션(sparse attention)은 명백한 해법처럼 보입니다. 지금까지의 시도는 크게 두 갈래로 나뉩니다. 고정 패턴 희소성(sliding-window, strided, block-local)은 정보를 버리는 방식이라 장거리 회상(long-range recall) 과제에서 실패합니다. 추론 시점 희소성(inference-time sparsity)에 속하는 KV 캐시 가지치기(KV cache pruning), H2O, StreamingLLM은 밀집(dense) 어텐션으로 사전 학습된 모델에 사후에 적용되며, 모델 자체가 희소 패턴(sparse pattern)을 통해 정보를 흘려보내도록 학습된 적이 없기 때문에 잠재적인 속도 향상(speedup)의 일부만 회수합니다.

Native Sparse Attention(Yuan 외, DeepSeek + PKU + UW, ACL 2025 Best Paper, arXiv:2502.11089)은 이 두 문제를 동시에 해결합니다. 모델이 사전 학습 중에 학습하는 희소 패턴이면서, 실제 추론에서 연산 절감을 가져오는 커널 정렬형 알고리즘(kernel-aligned algorithm)입니다. 앞으로 2년 안에 NSA나 그 직계 후속 구조가 모든 최전선(frontier) 장문 문맥 모델의 기본 어텐션이 될 가능성이 높습니다.

사전 테스트

2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요

1.NSA는 세 개의 병렬 어텐션 가지(branch)를 사용합니다. 각 가지가 포착하는 것은 무엇인가요?

2.NSA가 이전 희소 어텐션 방법과 달리 '본질적으로 학습 가능(natively trainable)'하다고 불리는 이유는?

0/2 답변 완료

개념

세 개의 병렬 가지(branch)

각 쿼리(query)에 대해 NSA는 KV 캐시의 서로 다른 세 가지 관점을 대상으로 어텐션을 세 번 실행합니다.

  1. 압축 가지(Compressed branch). 토큰을 블록 크기 l(보통 32 또는 64)로 묶고, 각 블록을 작은 학습형 다층 퍼셉트론(learned MLP)으로 요약 토큰 하나로 압축합니다. 쿼리는 이 압축 토큰들에 주의를 기울여(attend) 전체 시퀀스의 거친 단위 관점(coarse-grained view)을 얻습니다.

  2. 선택 가지(Selected branch). 압축 가지의 어텐션 점수(attention score)를 활용해 현재 쿼리와 가장 관련 있는 상위 k개 블록을 찾습니다. 그 블록의 세밀한, 즉 압축되지 않은(uncompressed) 토큰을 읽어 들여 쿼리가 이들 전체에 주의를 기울입니다. 압축 가지의 어텐션을 선택을 위한 라우팅 신호(routing signal)로 생각하면 됩니다.

  3. 슬라이딩 윈도우 가지(Sliding-window branch). 쿼리는 가장 최근 W개(보통 512개) 토큰에 주의를 기울여 국소 문맥(local context)을 봅니다. 이 가지는 구문(syntax)이나 국소 상호 참조(local coreference)처럼 다른 두 가지가 놓치기 쉬운 구조 중심의 단거리 패턴(short-range pattern)을 포착합니다.

세 가지의 출력은 위치별로 학습되는 게이트로 결합됩니다.

out = g_cmp * out_cmp + g_sel * out_sel + g_win * out_win

g_cmp, g_sel, g_win은 쿼리를 입력으로 받는 작은 MLP에서 나온 게이트 가중치입니다. 합이 반드시 1일 필요는 없으며, 세 가지를 독립적으로 가중할 수 있습니다.

왜 "본질적으로 학습 가능(natively trainable)"인가

선택 단계, 즉 상위 k개 블록을 고르는 동작은 이산적(discrete)입니다. 이산 연산은 기울기 흐름(gradient flow)을 끊어 버립니다. 이전 희소 어텐션 연구들은 선택을 통한 역전파(backpropagation; backprop)를 아예 건너뛰거나(학습이 제한됨), 추론 시 실제 희소성을 만들지 못하는 연속 완화(continuous relaxation)에 기댔습니다.

NSA는 이 문제를 우회합니다. 압축 가지의 어텐션 자체가 전체 시퀀스에 대한 미분 가능한 거친 단위 어텐션입니다. 상위 k 연산은 압축 가지에서 이미 계산한 상위 어텐션 점수를 그대로 재사용하여, 어떤 세밀한 블록을 메모리에서 적재(load)할지를 결정할 뿐입니다. 기울기는 압축 가지의 점수를 통해 흐르며, 이 점수는 압축 출력과 선택 로직 양쪽에 동시에 영향을 줍니다. 선택된 블록이 최종 출력에 기여하는 부분 또한 미분 가능합니다. 미분 불가능한 top_k 연산은 순전파(forward) 계산 그래프상에서는 사실상 아무 일도 하지 않는(no-op) 동작이며, 단지 메모리에서 어떤 블록을 적재할지를 제어할 뿐입니다.

이런 구조 덕분에 NSA는 사전 학습에서 전체 모델과 함께 처음부터 끝까지 학습할 수 있습니다. 모델은 세 가지를 통해 정보를 동시에 흘려보내는 방법을 학습하고, 그 결과 추론 시점에 실제로 약속한 속도 향상을 내는 희소 패턴이 형성됩니다.

하드웨어 정렬형 커널(Hardware-aligned kernel)

NSA의 커널(kernel)은 최신 GPU 메모리 계층(memory hierarchy)에 맞추어 설계됩니다. 커널은 그룹 쿼리 어텐션(Grouped-Query Attention; GQA) 그룹 단위로 쿼리를 적재하고(바깥 루프), 그룹별로 해당하는 희소 KV 블록을 가져온 뒤(안쪽 루프), SRAM 위에서 어텐션을 실행합니다. 각 쿼리 그룹이 동일한 선택 블록을 보기 때문에, 즉 선택이 쿼리 헤드(query-head)별이 아니라 쿼리 그룹(query-group)별로 이루어지기 때문에, KV 적재 비용이 그룹 전체에 걸쳐 상쇄(amortize)되고 산술 강도(arithmetic intensity)가 높게 유지됩니다.

논문은 64k 디코딩에서 Triton 커널이 FlashAttention보다 9배 빠르게 실행된다고 보고합니다. 속도 향상 비율은 시퀀스 길이가 길어질수록 더 커지며, 순전파 커널과 역전파 커널이 모두 제공됩니다.

연산 예산(compute budget)

N을 시퀀스 길이, l을 압축 블록 크기, k를 상위 k 선택 개수, w를 슬라이딩 윈도우 크기, b를 선택된 블록 크기라고 합시다(보통 b = l입니다).

  • 압축 가지: 쿼리당 O(N/l)개의 키(key)를 보므로 전체는 O(N * N / l)입니다.
  • 선택 가지: 쿼리당 O(k * b)개의 키를 보므로 전체는 O(N * k * b)입니다.
  • 슬라이딩 가지: 쿼리당 O(w)개의 키를 보므로 전체는 O(N * w)입니다.

총합은 O(N * (N/l + k*b + w))입니다.

N = 64k, l = 64, k = 16, b = 64, w = 512라면 쿼리당 비용은 1000 + 1024 + 512 = 2536 키입니다. 풀 어텐션은 64000 키이므로 25배의 연산 절감입니다.

N = 128k, l = 64, k = 16, b = 64, w = 512라면 쿼리당 비용은 2000 + 1024 + 512 = 3536 키입니다. 풀 어텐션은 128000 키이므로 36배의 절감입니다. 이득은 시퀀스 길이와 함께 커지며, 이것이 NSA의 핵심입니다.

다른 방법들과의 비교

방법미분 가능실제 추론 속도 향상장거리 회상
슬라이딩 윈도우 단독(Sliding window only)실패
스트라이드/블록 희소(Strided / block-sparse)부분적
KV 가지치기(H2O, StreamingLLM)해당 없음 (추론 시점)부분적
MoBA (Moonshot)부분적좋음
NSA예 (본질적으로)예 (64k에서 9배)풀 어텐션과 동등

MoBA(Moonshot, arXiv:2502.13189)는 동시기에 공개된 연구로, 어텐션 블록에 전문가 혼합(Mixture of Experts; MoE) 원리를 적용해 비슷하게 셋이 하나보다 낫다는 접근을 취합니다. NSA와 MoBA는 2026년의 장문 문맥 사전 학습에서 반드시 알아야 할 두 아키텍처입니다.

직접 만들기

code/main.py는 짧은 합성 시퀀스 위에서 세 가지를 구현하고 다음을 보여줍니다.

  • 압축 MLP. 학습 목적의 명확성을 위해 단순한 평균 풀링(mean-pool) 기준선(baseline)을 사용합니다. 실제 NSA는 학습형 MLP를 씁니다.
  • 압축 가지의 점수가 이끄는 상위 k 블록 선택.
  • 마지막 w개 토큰에 대한 슬라이딩 윈도우 어텐션.
  • 게이트로 결합된 출력(gated combination).
  • 풀 어텐션과 비교하는 키 개수(compute-count) 출력.

Step 1: 토큰을 블록으로 압축하기

def compress(K, l):
    n = len(K)
    n_blocks = (n + l - 1) // l
    out = []
    for b in range(n_blocks):
        start, end = b * l, min((b + 1) * l, n)
        block = K[start:end]
        summary = [sum(row[d] for row in block) / len(block) for d in range(len(K[0]))]
        out.append(summary)
    return out

Step 2: 압축 가지 어텐션

쿼리를 압축된 키에 대해 소프트맥스(softmax) 어텐션으로 실행합니다. 압축 가지의 점수는 상위 k 선택을 위한 신호 역할도 겸합니다.

Step 3: 상위 k 블록 선택

점수가 가장 높은 k개 압축 블록의 인덱스를 고릅니다. 해당 블록의 원래 압축되지 않은 토큰을 적재하고 그 위에서 어텐션을 실행합니다.

Step 4: 슬라이딩 윈도우 어텐션

마지막 w개 토큰을 가져와 그 위에서 표준 어텐션을 실행합니다.

Step 5: 게이트와 결합(gate + combine)

쿼리를 입력으로 받는 작은 MLP가 세 개의 게이트 가중치를 만듭니다. 최종 출력은 세 가지 출력의 가중합(weighted sum)입니다.

Step 6: 키 개수 세기

가지별로 쿼리당 주의를 기울인 키 개수와 전체 키 개수를 출력하고, N 즉 풀 어텐션 비용과 비교합니다. l = 32, k = 4, w = 128인 1024-토큰 합성 시퀀스에서 NSA는 쿼리당 32 + 128 + 128 = 288개의 키를 보고, 풀 어텐션은 1024개를 보므로 약 3.5배 적습니다.

사용해보기

NSA는 DeepSeek 자체의 장문 문맥 사전 학습 파이프라인에서 이미 사용되고 있습니다. 2026년 4월 기준 공개된 추론 스택(public inference stack)의 통합 현황은 다음과 같습니다.

  • DeepSeek 내부: 기본 채택(native). 공개된 가중치는 NSA 또는 그 후속인 DSA(Deepseek Sparse Attention)를 사용합니다.
  • vLLM: DeepSeek-V3.x 가중치를 위한 실험적(experimental) NSA 지원을 개발 중입니다.
  • SGLang: NSA 벤치마크가 공개되어 있으며, 운영(production) 경로는 vLLM을 따라갑니다.
  • llama.cpp / CPU: 지원하지 않습니다. CPU 처리량(throughput) 수준에서는 커널 분해의 오버헤드가 이득보다 큽니다.

NSA를 고려할 만한 상황은 다음과 같습니다.

  • 64k를 넘는 문맥을 목표로 하는 사전 학습이나 추가 학습(continued training)이며, 충분한 연산 예산이 있을 때.
  • DeepSeek 계열의 장문 문맥 체크포인트(checkpoint)를 추론할 때. 가중치 자체가 NSA에 맞춰져 있습니다.

반대로 NSA가 어울리지 않는 상황은 다음과 같습니다.

  • 기존 밀집 어텐션으로 사전 학습된 모델을 서빙하는 경우. 추가 학습 없이 NSA를 사후 결합(retrofit)할 수는 없습니다.
  • 문맥이 16k 미만인 경우. 세 가지 분기 자체의 오버헤드가 절감 효과를 압도합니다.
  • 배치 크기 1(batch-1)의 대화형 채팅(interactive chat). 지연 시간(latency)에 민감한 디코딩이 이득을 보긴 하지만, 긴 문맥에서만 의미 있는 차이가 납니다.

산출물 만들기

이 강의는 outputs/skill-nsa-integrator.md를 만듭니다. 장문 문맥 사전 학습 실행 명세(specification)가 주어지면 NSA 통합 계획(integration plan)을 작성합니다. 압축 블록 크기, 상위 k, 슬라이딩 윈도우, 게이트 MLP의 너비, 커널 선택, 그리고 아키텍처 변경을 정당화할 장문 문맥 평가(eval) 항목을 포함합니다.

연습문제

  1. 쉬움 — 1024-토큰 합성 시퀀스에서 code/main.py를 실행합니다. (l, k, w)를 세 가지 사전 설정(preset)으로 훑어 보고(sweep) 키 개수를 출력합니다. 건초 더미 속 바늘 찾기(needle-in-haystack) 테스트에서 풀 어텐션 대비 95% 회상률을 유지하면서도 쿼리당 키 개수가 가장 적은 설정을 찾습니다.

  2. 중간 — 평균 풀링 압축기를 작은 학습형 MLP(2-layer, hidden 32)로 교체합니다. 신호가 블록 평균인 합성 과제에서 학습시킨 뒤, 미사용 데이터(held-out data)에서 평균 풀링 기준선과의 퍼플렉서티(perplexity) 차이를 측정합니다.

  3. 중간 — 게이트 MLP를 구현합니다. 쿼리를 입력으로 받아 스칼라 세 개를 출력합니다. 무작위 쿼리에서는 거의 균등한 가중을 보이고, 쿼리가 멀리 떨어진 블록과 맞물릴(hit) 때는 선택 가지에 큰 가중을 주는지 확인해 게이트가 합리적으로 동작하는지 보입니다.

  4. 어려움 — 128k 문맥의 NSA 적용 70B 모델에 대해 KV 캐시 메모리 예산을 계산합니다. KV 헤드 수는 8, 헤드 차원은 128, 데이터 형식은 BF16입니다. 풀 어텐션 및 다중 잠재 어텐션(Multi-head Latent Attention; MLA, Phase 10 · 14에서 MLA의 수치를 다루었습니다)과 비교하고, NSA의 세밀한 가지 KV 캐시가 풀 어텐션과 같아지는 시퀀스 길이를 찾습니다.

  5. 어려움 — NSA 논문(arXiv:2502.11089)의 4절을 읽고, 압축 가지의 어텐션 점수를 상위 k 선택에 재사용하는 이유를 세 문장으로 설명합니다. 별도의 라우팅 점수를 따로 계산하지 않는 까닭을 기울기 흐름과 연결해 답합니다.

핵심 용어

용어흔한 설명실제 의미
압축 가지(Compressed branch)"거친 관점(coarse view)"블록 평균 키 위의 어텐션. 쿼리당 O(N/l)개의 키로 전역 문맥(global context)을 제공한다.
선택 가지(Selected branch)"상위 k 블록(top-k blocks)"압축 가지 점수가 가장 높은 k개 블록의 세밀한 토큰 위에서 수행되는 어텐션이다.
슬라이딩 윈도우(Sliding window)"국소 문맥(local context)"단거리 패턴을 위해 최근 W개 토큰에 주의를 기울이는 어텐션이다.
본질적 학습 가능성(Native trainability)"희소성을 켠 채로 사전 학습"희소 패턴을 추론 시 사후에 덧붙이지 않고 사전 학습 단계에서부터 학습한다.
압축 블록 크기 l"거친 관점의 그룹 크기"몇 개의 토큰을 하나의 요약으로 합칠지 정한다. 보통 32~64이다.
Top-k"보관할 블록 수"압축된 블록 중 압축되지 않은 토큰을 읽어 들일 블록의 개수. 보통 16이다.
슬라이딩 윈도우 W"국소 어텐션 반경(local attention radius)"보통 512이다. 짧으면 국소 일관성(local coherence)이 떨어지고, 길면 연산을 낭비한다.
가지 게이트(Branch gate)"세 가지를 섞는 방법"세 가지의 기여도를 가중하는 위치별 MLP 출력이다.
하드웨어 정렬(Hardware alignment)"커널 친화적 희소성"실제 GPU 커널이 이론적 속도 향상을 달성하도록 희소 패턴을 선택하는 일이다.
DSA"NSA의 후속"Deepseek Sparse Attention. DeepSeek 계열에서 NSA의 뒤를 이은 아키텍처이다.

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

main
Code

산출물

이 강의에서 생성된 프롬프트, 스킬, 코드 산출물 1개

nsa-integrator

Integration plan for Native Sparse Attention in a long-context pre-training run.

Skill

확인 문제

3문제 · 모두 맞추면 완료 표시가 가능합니다

1.N=64k, l=64, k=16, b=64, w=512일 때, NSA에서 쿼리당 주의를 기울이는 키 수 vs 풀 어텐션은?

2.기존 밀집 어텐션으로 사전학습된 모델에 NSA를 사후 결합(retrofit)할 수 없는 이유는?

3.문맥 길이가 16k 미만일 때 NSA가 오히려 역효과를 낼 수 있는 이유는?

0/3 답변 완료

추가 문제 풀기

AI가 강의 내용을 바탕으로 새로운 문제를 생성합니다