Speculative decoding: 언제 그리고 왜 실제로 추론 속도를 높이는가
요약
LLM 추론 시 발생하는 메모리 제한(memory-bound) 문제를 해결하기 위한 Speculative decoding 기술을 설명합니다. 작은 드래프트 모델이 토큰을 미리 제안하고 타겟 모델이 이를 검증함으로써, 출력 품질 저하 없이 추론 속도를 획기적으로 높이는 원리를 다룹니다.
핵심 포인트
- LLM 추론은 연산보다 메모리 대역폭에 제한을 받는 경우가 많음
- Speculative decoding은 출력 품질을 유지하며 추론 속도를 가속함
- 작은 드래프트 모델이 제안하고 큰 타겟 모델이 검증하는 방식
- 메모리 대역폭 효율을 높여 TTFT(첫 토큰 생성 시간)를 단축함
Speculative decoding: 언제 그리고 왜 실제로 추론 속도를 높이는가
여러분의 채팅 엔드포인트(endpoint)는 초당 200개의 요청을 처리합니다. 모델은 70B Llama 3 파인튜닝(fine-tune) 모델입니다. GPU 사용률은 78%에 머물러 있지만, 사용자 측면의 지연 시간(latency)은 여전히 좋지 않습니다. 중앙값(median) 요청의 첫 번째 토큰 생성 시간(first token)은 380ms이며, P99는 1.1s입니다. 단순하게 읽자면 "더 큰 서버가 필요하다"라고 생각할 수 있습니다. 하지만 실제 분석 결과는 GPU가 연산 제한(compute-bound)이 아니라 메모리 제한(memory-bound) 상태라는 것입니다. 대부분의 시간은 HBM에서 SM(Streaming Multiprocessor)으로 가중치(weights)와 KV-캐시(KV-cache) 상태를 한 번에 하나의 토큰씩 전송하고, 다음 토큰을 기다리는 데 소비됩니다. Speculative decoding(추측적 디코딩)은 모델이 실제로 샘플링하는 내용을 바꾸지 않으면서, 한 번에 하나의 토큰씩 처리하던 파이프라인을 한 번에 여러 개의 토큰을 처리하는 파이프라인으로 전환하는 기술입니다. 저희의 경우, 동일한 하드웨어와 동일한 70B 가중치를 사용하여 p50 TTFT(Time To First Token)를 380ms에서 140ms로 낮추었습니다.
이 기술이 무엇인지, 변형(variants)에는 무엇이 있는지, 그리고 언제 더 이상 공짜 점심이 아니게 되는지에 대해 알아보겠습니다.
이것이 실무에서 중요한 이유
단일 GPU에서 자기회귀(autoregressive) LLM의 처리량(throughput) 상한선은 FLOPs(부동 소수점 연산량)가 아니라, 한 토큰 분량의 로짓(logits)과 다음 토큰 분량의 어텐션(attention) 상태를 이동시키는 비용에 의해 결정됩니다. 메모리 제한(memory-bound) 워크로드에서 모델의 파라미터(parameters)를 두 배로 늘리면 토큰당 시간도 대략 두 배로 늘어나지만, SM이 수행할 수 있는 FLOPs가 두 배가 되지는 않습니다. SM은 유휴(idle) 상태로 머물러 있기 때문입니다. Speculative decoding은 매 K개 토큰마다 타겟(target) 모델에 대해서만 무거운 순전파(forward pass)를 수행하고, 타겟 모델이 한 개의 토큰을 처리할 시간에 K개의 토큰을 제안하는 훨씬 작은 드래프트(draft) 모델로 그 간극을 채움으로써 이 문제를 해결합니다.
사람들이 문제가 닥치기 전까지 잊어버리는 속성 중 하나는, Speculative decoding(추측적 디코딩)이 정확한 (exact) 디코딩 가속기라는 점입니다. 모든 제안된 토큰은 타겟 모델에 의해 검증되기 때문에, 출력 분포는 타겟 모델을 단독으로 실행하는 것과 증명 가능할 정도로 동일합니다. 만약 타겟 모델이 제안을 거부했을 경우, 알고리즘은 수정된 분포에서 다시 샘플링(resample)합니다. 만약 타겟 모델이 이를 수락했을 경우, 해당 토큰을 생성하는 비용은 K번이 아닌 단 한 번만 지불됩니다. 즉, 출력 품질을 속도와 맞바꾸는 것이 아닙니다. VRAM과 엔지니어링 노력을 속도와 맞바꾸는 것입니다.
알고리즘의 실제 작동 방식
원래의 공식은 DeepMind의 Chen, Borgeaud, Irving, Lespiau, Sifre의 논문, "Accelerating Large Language Model Decoding with Speculative Sampling" (2023년 2월)에서 유래되었습니다. 설정은 다음과 같습니다:
- 드래프트 모델 (draft model) $M_q$가 $K$개의 후보 토큰을 자기회귀적 (autoregressively)으로 하나씩 생성합니다. 이 모델은 타겟 모델보다 훨씬 작습니다.
- 타겟 모델 (target model) $M_p$가 이 $K+1$개의 위치(제안된 $K$개의 토큰과 하나의 lookahead)에 대해 단 한 번의 순전파 (forward pass)를 수행합니다.
- 각 제안된 토큰 $x_t$에 대해, 수락 확률 $r = ext{min}(1, M_p(x_t) / M_q(x_t))$를 계산합니다.
- $[0, 1)$ 범위 내에서 균등 분포 $u$를 샘플링합니다. 만약 $u < r$이면 $x_t$를 수락합니다. 그렇지 않으면 거부하고 정규화된 잔차 분포 (normalized residual distribution)에서 다시 샘플링합니다.
사이클당 수락된 토큰의 수는 확률 변수입니다. 만약 드래프트 모델이 타겟 모델과 잘 정렬되어 있다면 — 즉, 분포가 타겟 모델과 유사하다면 — 기대되는 수락 길이(expected accepted length)가 길어지고 속도 향상(speedup)도 커집니다. 만약 두 모델이 서로 다르다면 (다른 토크나이저 오프셋, 다른 학습 데이터, 다른 미세 조정 (fine-tune)) 대부분의 제안이 거부되며, 아무런 이득 없이 드래프트 비용만 지불하게 됩니다.
flowchart LR
A[Prompt] --> B[Draft model Mq<br/>generates K tokens<br/>autoregressively]
B --> C[Target model Mp<br/>one forward pass<br/>over K+1 positions]
...
사이클 비용은 대략 다음과 같습니다: $M_q$의 $K$번의 순전파 (forward pass) + $M_p$의 1번의 순전파 (forward pass) + $K$번의 저렴한 로짓 (logit) 비교. 수락된 토큰당 절약된 총 시간은 $K$번의 $M_p$ 순전파 (가속되지 않은 디코더가 수행했을 작업)와 실제 사이클 비용 사이의 차이입니다.
변형 모델 (Variants): 어떤 제안 모델 (proposer)을 사용할 것인가
이 분야는 매우 빠르게 발전해 왔습니다. 단순한 초안 모델 (draft model, 예: 70B 메인 모델을 위한 1B 모델)도 여전히 작동하지만, 몇몇 더 스마트한 변형 모델들이 권장 기본값(recommended-default) 자리를 차지했습니다. vLLM의 speculative decoding docs (v0.22.0, 2026년 5월 출시)에는 9가지 내장 메서드가 나열되어 있으며, 대부분의 팀에게 중요한 것은 다음과 같습니다.
| 메서드 (Method) | 정의 | 최적의 용도 | 비용 / 리스크 |
|---|---|---|---|
| EAGLE / EAGLE-2 / EAGLE-3 (Li et al., 2024) | 다음 토큰이 아닌 다음 레이어의 은닉 상태 (hidden state)를 예측하도록 훈련된 작은 헤드 (head) 모델. 레이어 1에서 타겟 모델을 포착하여 외삽 (extrapolate)함. | 범용적이며, 원시 수락 길이 (raw acceptance length)가 가장 좋음. Llama 스타일 모델의 권장 기본값. | 타겟 모델마다 훈련된 EAGLE 헤드가 필요함. |
| ... | |||
vLLM 문서의 정성적 표는 대부분의 블로그 요약보다 더 날카롭습니다. 낮은 QPS (지연 시간 중심) 환경에서는 EAGLE과 MTP가 가장 높은 이득을 주는 반면, 높은 QPS (처리량 중심) 환경에서는 초안 모델의 비용이 분할 상환 (amortized)되기 때문에 그 격차가 줄어듭니다. n-gram과 suffix 방식은 초안 모델 없이도 두 환경 모두에서 완만하고 예측 가능한 이득을 제공합니다.
vLLM을 사용한 작동 예시
다음은 오프라인 배치 생성 (offline batched generation)을 위해 EAGLE을 사용하는 실제 실행 가능한 설정입니다. 이는 vLLM 리포지토리의 eagle.md example에서 직접 가져온 것입니다:
from vllm import LLM, SamplingParams
prompts = ["The future of AI is"]
...
서버의 경우, CLI 형태는 다음과 같습니다:
vllm serve meta-llama/Meta-Llama-3-8B-Instruct \
--tensor-parallel-size 4 \
--speculative-config '{
...
이를 프로덕션 환경에서 실행할 때의 두 가지 참고 사항입니다:
num_speculative_tokens는 알고리즘의 $K$ 값입니다. 기본값은 5입니다. 이 값을 너무 높게(8, 16) 설정하면 수용 길이(acceptance length)가 비례해서 늘어나지 않으면서 사이클당 비용만 증가합니다. 7B/8B 타겟 모델에 대해 EAGLE을 사용할 때는 보통 2~4로 설정하는 것이 최적이며, 70B 타겟의 경우 최적의 $K$ 값은 더 높아집니다.draft_tensor_parallel_size는 초안 모델(draft model)이 실행되는 GPU의 수입니다. 초안 모델이 타겟 모델과 동일한 병렬성(parallelism)을 사용하게 해서는 안 됩니다. 이는 목적에 어긋납니다. 타겟 모델이 8개의 GPU에 걸쳐 있더라도 초안 모델은 하나의 GPU에서 실행되어야 합니다.
EAGLE 헤드를 건너뛰고 코드 완성(code-completion) 워크로드에서 n-gram 제안자(proposer)를 바로 시도해보고 싶다면 다음과 같이 설정하십시오:
# config.yaml — --speculative-config "$(cat config.yaml)"와 함께 전달
method: ngram
num_speculative_tokens: 5
초안 모델이 필요하지 않고, 추가적인 VRAM도 필요 없으며, 수용 모델(acceptance model)도 필요 없습니다. 반복적인 import 문과 함수 시그니처(function signatures)가 있는 코드에서는 1.4~1.8배의 속도 향상을 볼 수 있지만, 개방형 채팅(open-ended chat)에서는 1.0배의 속도가 나와 왜 시도했는지 의문이 들 수도 있습니다.
수용률(Acceptance rate)과 실제로 중요한 지표
속도 향상(Speedup)은 **사이클당 평균 수용 토큰 수 ($\mu$)**의 함수입니다. 단일 스트림 워크로드에 대한 관계식은 대략 다음과 같습니다:
speedup \approx (1 + \mu) / ( (1 + \mu) * draft_cost_ratio + 1 )
여기서 draft_cost_ratio는 타겟 모델의 토큰당 비용에 대한 초안 모델의 토큰당 비용 비율입니다. 타겟 비용의 10%를 차지하는 초안 모델의 경우, 그래프는 $\mu \approx 4$ 부근에서 굴곡(knee)이 발생합니다. 만약 $\mu$가 1 미만으로 떨어지면 알고리즘은 결과적으로 손해입니다. 이것이 "Speculative decoding을 통해 2배 속도 향상"이라고 주장하는 모든 벤치마크 보고서에서 반드시 확인해야 할 단 하나의 숫자입니다. 만약 평균 수용 토큰을 보고하지 않는다면, 그 속도 향상은 재현 불가능한 것입니다.
측정하십시오. vLLM은 examples/features/speculative_decoding/spec_decode_offline.py에서 요청 수준의 수용률 (acceptance rate)을 공개합니다. 운영 환경에서 플래그를 켜기 전에, 귀하의 트래픽을 대표하는 샘플에 대해 이를 실행해 보십시오. HumanEval 프롬프트에서 μ = 4.2를 기록하는 초안 모델 (draft model)이 귀하의 고객 지원 채팅 코퍼스(corpus)에서는 μ = 1.1로 떨어질 수 있습니다. 동일한 가중치라도, 세상이 다르면 결과도 다릅니다.
흔한 함정들
팀들이 처음 시도할 때 빠지기 쉬운 몇 가지 함정은 다음과 같습니다:
-
초안 모델과 타겟 모델 간의 토크나이저 불일치 (Tokenizer mismatch). 초안 모델과 타겟 모델이 서로 다른 BPE 병합 (merges) 방식을 사용하거나 서로 다른 추가 특수 토큰 (special tokens)을 가지고 있다면, 제안된 토큰 ID가 초안 모델에는 유효하더라도 타겟 모델에는 유효하지 않을 수 있습니다. 수용 확인 (acceptance check) 프로세스는 여전히 실행되지만, 수용률은 0에 가깝게 붕괴됩니다. 특정 타겟 모델을 위해 공개된 EAGLE 헤드 (EAGLE heads)는 이미 정렬되어 있지만, 임의로 맞춘 초안 모델 쌍은 그렇지 않은 경우가 많습니다.
-
일치하지 않는 채팅 템플릿 (Chat template). 투기적 디코딩 (Speculative decoding)은 초안 모델이 시스템 프롬프트, 채팅 템플릿, 그리고 모든 도구 호출 (tool calls)을 포함하여 타겟 모델이 보는 것과 정확히 동일한 프롬프트 접두사 (prompt prefix)를 보도록 요구합니다. 만약 서빙 레이어 (serving layer)가 프롬프트가 모델에 도달한 후에 템플릿을 적용한다면 초안 모델과 타겟 모델 모두 동일한 템플릿을 받게 되지만, 타겟 모델에는 템플릿이 적용된 프롬프트를 캐싱하고 초안 모델에는 가공되지 않은 (raw) 프롬프트를 사용한다면 정렬이 깨지게 됩니다.
-
약한 초안 모델과 높은
num_speculative_tokens설정. 사이클당 비용은 K에 따라 선형적으로 증가합니다. μ = 1.5를 달성하는 초안 모델의 경우, K를 5에서 10으로 두 배 늘리면 거절된 사이클당 낭비되는 작업량도 대략 두 배로 늘어납니다. 추측하지 말고 벤치마크를 수행하십시오. -
탐욕적 디코딩 (Greedy decoding)과의 상호작용. 투기적 디코딩의 수용 확률은 확률적 샘플링 (stochastic sampling)에 대해서는 잘 정의되어 있지만, 순수 탐욕적 한계 (temperature 0)에서는 수학적 구조가 무너집니다. 토큰은 두 모델 모두의 argmax이거나 (수용), 그렇지 않거나 (한 번의 시도 후 거절) 둘 중 하나입니다. 탐욕적 모드에서의 수용률은 낮은 온도의 샘플링보다 더 낮습니다. 항상 temperature 0을 사용하는 채팅 제품을 서비스한다면, 블로그 벤치마크에서 제시하는 것보다 30~50% 적은 속도 향상을 예상해야 합니다.
-
용량 계획(capacity planning) 시 초안 모델(draft model)의 VRAM 포함을 잊는 경우. 1B EAGLE 헤드는 작지만 (~bf16 기준 약 2 GB), 만약 H100의 VRAM을 이미 95% 사용 중이라면 초안 모델이 들어갈 공간이 없어 모델 로드 시점이 아닌 서비스(serve) 시점에 OOM (Out of Memory)이 발생할 것입니다.
사용하지 말아야 할 때
다음과 같은 경우에는 Speculative decoding (추측적 디코딩)이 적절한 도구가 아닙니다:
- 워크로드가 지연 시간(latency)이 아닌 처리량(throughput)에 제한을 받는 경우. 70B 모델에서 1,000개 이상의 동시 요청을 처리하며 대량의 배치 생성(bulk batched generation)을 수행하고 있다면, 이는 메모리 제한(memory-bound)이 아닌 연산 제한(compute-bound) 상황일 가능성이 높습니다. Speculative decoding은 개별 사용자에게는 도움이 되겠지만, 전체 초당 토큰 수(aggregate tokens/sec)는 크게 개선되지 않으며 초안 모델을 사용하는 비용은 실질적으로 발생합니다.
- 대상 모델에 적합한 초안 모델을 찾을 수 없는 경우. 공개된 EAGLE 헤드가 없다면, 이를 직접 학습시키는 것은 그 자체로 하나의 프로젝트가 됩니다 (vllm-project/speculators 라이브러리가 2026년 4월 기준 v0.5.0 버전으로 도움을 줄 수 있지만, 여전히 대상 모델의 학습 데이터 분포가 필요합니다). 작은 데이터셋을 사용한 일회성 미세 조정(fine-tune)의 경우, 초안 모델을 학습시키는 엔지니어링 비용이 지연 시간 단축으로 얻는 이득을 초과하는 경우가 많습니다.
- 출력이 짧고 온도가 높은(high-temperature) 경우. Temperature (온도) 1.0에서의 20토큰 생성은 거절(reject)될 확률이 20번 존재하며, 마지막의 재샘플링된(resampled) 토큰은 추측에 불과합니다. 수락 확률(acceptance math)은 여전히 유효하지만, 비용을 분산시킬 토큰 수가 너무 적기 때문에 사이클당 비용이 지배적이게 됩니다. 짧은 형태의 고엔트로피(high-entropy) 출력의 경우에는 Prefix caching (접두사 캐싱) 및 KV-cache 양자화(quantization)가 더 효과적일 것입니다.
- 이미 기본값이 아닌 서빙 설정을 사용 중인 경우. FlashInfer, FP8 가중치, Paged attention, Chunked prefill, 그리고 분리된 Prefill/Decode (disaggregated prefill/decode)를 사용하고 있다면, Speculative decoding이 이 모든 설정과 호환되는지 확인해야 합니다.
--speculative-config의 플래그들이 엔진의 나머지 설정들과 항상 깔끔하게 조합되는 것은 아닙니다.
요약 (TL;DR)
- **Speculative decoding (추측적 디코딩)**은 작은 초안 모델 (draft model)로 K개의 토큰을 생성하고, 타겟 모델의 단일 순전파 (forward pass) 과정에서 이를 검증합니다. 이는 정확 (exact) 합니다. 즉, 출력 분포가 타겟 모델만 단독으로 실행했을 때와 증명 가능할 정도로 동일합니다.
- 원문 논문은 Chen et al., DeepMind, 2023입니다. 현대의 지배적인 변형 방식은 토큰 레벨이 아닌 은닉 상태 (hidden-state) 레벨에서 초안을 작성하는 EAGLE-3입니다.
- vLLM v0.22.0 (2026년 5월)은 EAGLE, MTP, 초안 모델 (draft model), PARD, MLP, n-gram, suffix, 은닉 상태 추출 (hidden-state extraction), 그리고 커스텀 제안자 훅 (custom-proposer hook) 등 9가지 내장 방식을 제공합니다.
- 측정해야 할 단일 지표는 **사이클당 평균 수락 토큰 수 (mean accepted tokens per cycle, μ)**입니다. μ = 4–5 정도면 양호합니다. 2 미만이라면 초안 생성 비용을 들일 가치가 없습니다.
- 이는 메모리 대역폭에 제한을 받는 (memory-bound), 저~중간 QPS (Queries Per Second) 워크로드에서의 지연 시간 (latency) 최적화 기법입니다. 처리량 (throughput)을 높이기 위한 편법이 아닙니다. 타겟 모델에 적합한 고품질 EAGLE 헤드를 사용하고, 벤치마킹을 위해 현실적인 트래픽 샘플을 결합하여 사용하십시오.
다음 포스트: KV 캐시 양자화 (KV cache quantization) — FP8 / INT8 KV 캐시가 메모리 예산을 어떻게 변화시키는지, 그리고 왜 일부 방식이 Speculative decoding의 수락률 (acceptance rate)을 조용히 망가뜨리는지에 대해 다룹니다.
제가 다루지 않은 타겟 모델에 대한 초안 모델 추천이 있다면 댓글로 남겨주세요. 후속 포스트를 위해 커뮤니티의 선택을 수집하고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기