벤치마크 시트에서는 2× 속도 향상이 나오는데 실제 서빙 서버에서 측정해보면 거의 차이가 없거나 오히려 느려지는 경우가 있다. Speculative Decoding을 도입한 팀이라면 한 번쯤 겪는 상황이다. 문제의 뿌리는 하나의 변수에 있지 않다 — 수락률(acceptance rate), 배치 크기, KV 캐시 압력 세 요소가 서로 맞물려 speedup을 결정하기 때문이다.
Draft-Verify 루프: 핵심만
Draft model이 γ개의 토큰을 순차적으로 생성한다. Target model이 이 γ개 토큰을 1회 forward pass로 병렬 검증한다 — autoregressive 방식이라면 γ번의 개별 forward pass가 필요할 자리다. 검증 결과에 따라 수락된 토큰들을 commit하고, 거부된 지점부터 다시 draft를 시작한다.
이 구조가 빠른 이유는 target model의 1번 forward pass가 최대 γ+1개 토큰을 처리할 수 있기 때문이다. 단, "최대"다. 실제로 몇 개가 수락되는지는 수락률에 달려 있다.
수락률은 태스크 유형에 따라 크게 달라진다
수락률(α)이 speedup을 결정하는 1차 변수다. 같은 모델·같은 draft 길이에서도 태스크에 따라 α가 크게 벌어진다.
vLLM + EAGLE-2 기준 태스크 유형별 수락률 분포:
| 태스크 | 수락률(α) | 비고 |
|---|---|---|
| 코드 완성 | ~0.88 | 고정 문법 템플릿, 반복 패턴 |
| 요약 (CNN/DM) | ~0.72 | 구조적 문장, 예측 가능성 높음 |
| 한국어 자유 생성 | ~0.61 | 단어 선택 폭이 넓고 분포가 다양 |
| 수학 추론 (GSM8K) | ~0.55 | 계산 단계마다 분기 가능성 높음 |
코드 완성이 높은 이유는 고정된 문법 패턴 덕분이다. Draft model이 return 다음에 뭐가 올지 맞추기가 훨씬 쉽다. 수학 추론은 중간 계산 단계에서 여러 경로가 가능하고, draft model이 target model의 논리 전개를 항상 따라가지는 못한다.
Leviathan et al.의 speedup 수식에서 speculative step 1회당 기대 수락 토큰 수는:
E[accepted] = (1 - α^(γ+1)) / (1 - α)
α=0.88, γ=4이면 E≈4.4. α=0.55, γ=4이면 E≈2.0이다. 수락률 0.33 차이가 기대 토큰 수를 두 배 이상 벌린다. 수락률이 낮을 때 draft γ=4 단계는 순수 오버헤드가 된다 — draft model을 γ번 돌린 비용을 target model의 1 forward pass 이득으로 회수가 안 된다.
배치 크기가 커지면 이 이득이 사라지는 이유
Speculative Decoding의 speedup이 batch=1에서 가장 높고 배치가 커질수록 줄어드는 건 LLM decode 단계의 근본 특성에서 나온다.
소규모 배치에서 decode는 memory-bound 연산이다. GPU의 연산 유닛은 놀고 있고 HBM에서 가중치를 읽어오는 속도가 병목이다. 이 상황에서 target model의 verify pass는 "토큰 1개 처리"와 "토큰 γ+1개 처리" 사이의 비용 차이가 거의 없다 — 가중치 로딩이 병목이고, γ+1개의 attention 계산은 추가적인 메모리 이동 없이 같은 가중치 위에서 처리된다. speedup이 최대화되는 조건이다.
배치가 커지면 arithmetic intensity(연산량 / 메모리 이동량)가 올라가고 compute-bound 영역으로 진입한다. 이제 verify pass에서 γ+1개 토큰을 처리하는 비용이 실제로 커진다. 각 요청이 "draft γ개 생성 + verify 1회"의 긴 GPU 점유 사이클을 가져가므로, 전체 배치의 처리 효율이 떨어진다.
draft 길이 γ=4, 수락률 α=0.75 기준 배치 크기별 approximate speedup:
| Batch size | 연산 특성 | 이론 speedup |
|---|---|---|
| 1 | memory-bound | ~2.5× |
| 4 | memory→compute 전환 시작 | ~1.9× |
| 16 | 부분 compute-bound | ~1.2× |
| 32 | compute-bound | ~0.95× |
batch=32에서 1 미만이 나오는 건 draft model 실행 비용 + verify overhead가 단순 AR decode보다 무거워지는 시점이다. 같은 GPU 시간으로 AR decode를 그냥 돌렸으면 더 많은 토큰을 처리했다는 의미다.
배치와 speculative decoding의 상호작용을 분석한 논문에서도 batch=4, γ=3 조건에서 1.93×의 speedup이 측정됐다. 배치가 커질수록 이 수치가 낮아지는 게 일관된 패턴이다. 벤치마크 환경이 대부분 batch=1 또는 소수 고정 요청으로 측정되는 이유가 여기 있다 — 그 환경이 Speculative Decoding에 가장 유리한 조건이기 때문이다. 실제 서빙 환경의 혼합 트래픽에서는 배치가 동적으로 커지고, 측정값과의 간극이 생긴다.
Draft 단계가 KV 캐시에 가하는 압력
Draft 방식에 따라 메모리 풋프린트가 구조적으로 달라진다.
독립 draft model (예: Llama-68M을 Llama-70B의 draft로 사용): draft model이 전용 KV 캐시를 별도로 점유한다. Llama-68M은 모델 가중치 자체가 fp16 기준 약 0.27GB로 작지만, 배치 전체에 대한 KV 캐시가 따로 관리된다. 70B 서빙 GPU에서 draft model KV 캐시가 HBM을 먹으면, 같은 GPU에서 동시 처리 가능한 요청 수(max concurrent requests)가 줄어든다. 가중치와 활성화 메모리를 두 모델이 나눠 쓰는 구조다.
EAGLE / EAGLE-2: target model의 hidden state를 입력으로 받는 경량 draft head가 추가되는 구조다. 별도 draft model KV 캐시가 없다. 대신 draft 단계에서 생성한 투기 토큰들이 target model의 KV 캐시에 append되어야 하므로, verify 전후로 KV sequence length가 γ개만큼 늘어난다. Draft head 자체 파라미터는 약 0.5~0.6GB 수준으로, 독립 draft model보다 훨씬 작다. EAGLE-2 논문 기준으로 3.05×~4.26×의 speedup을 내면서 KV 메모리 오버헤드를 최소화하는 방향으로 설계됐다.
Medusa: target model에 여러 개의 decoding head를 추가해 +1, +2, ... 위치의 토큰을 병렬 예측한다. Tree attention을 통해 여러 후보 경로를 동시에 evaluate한다. KV 캐시 구조는 target model의 것을 완전히 공유하며, 별도 draft model KV 캐시가 없다. 하지만 tree attention에서 후보 경로 수에 비례해 KV compute가 증가한다.
세 방식 모두 "draft model 전용 KV 캐시를 갖는가 아닌가"를 기준으로 메모리 구조가 갈린다. 독립 draft model 방식은 편하지만, 같은 HBM에서 두 모델의 KV 캐시를 동시에 관리해야 하기 때문에 대규모 배치에서 불리하다.
Continuous Batching 스케줄러와의 충돌
vLLM 같은 continuous batching 스케줄러 관점에서 Speculative Decoding은 특이한 요청처럼 보인다.
일반 AR decode에서 각 요청은 "한 step = 한 토큰 = 짧고 균일한 GPU 점유"를 갖는다. 스케줄러가 새 요청을 끼워 넣거나 우선순위를 조정하기 쉽다.
Speculative Decoding을 켜면 하나의 요청이 "draft γ개 생성 + verify 1회"의 긴 사이클을 가져간다. 이 사이클 동안 다른 요청은 대기한다. 배치 내 일부 요청만 speculative decoding을 쓰는 혼합 상황에서는 특히 문제가 된다 — 긴 사이클의 요청이 스케줄러의 공정성(fairness)을 깨뜨리고 다른 요청의 TTFT(Time to First Token)를 높인다. 처리량(throughput) 자체는 괜찮더라도 지연 분포가 나빠진다.
preemption이 draft 중간에 발생하면: vLLM은 수락된 토큰만 commit하고 아직 verify되지 않은 draft 토큰은 폐기한다. draft γ개를 생성하는 데 쓴 compute가 그대로 낭비된다. 메모리 압박이 심하거나 요청 우선순위 변동이 잦은 환경에서 Speculative Decoding의 실질 gains가 급격히 줄어드는 이유다.
EAGLE vs Medusa vs Lookahead: 세 방식의 트레이드오프
| EAGLE-2 | Medusa | Lookahead | |
|---|---|---|---|
| Draft 방식 | target hidden state 기반 경량 head | target model에 추가 decoding head | n-gram prefix 매칭 |
| 수락률 | 높음 (코드 ~0.88, 텍스트 ~0.70) | 중간 (task-dependent) | 낮~중간 |
| 추가 KV 캐시 | 없음 (투기 토큰만 temporary append) | 없음 (target KV 공유) | 없음 |
| 추가 파라미터 | 여러 head (~수백MB) | 없음 | |
| 배치 민감도 | 중간 | 중간~높음 | 낮음 |
| 별도 학습 필요 | 있음 (draft head 학습) | 있음 (head 추가 fine-tuning) | 없음 |
| 최적 환경 | latency-critical, 소규모 배치 | 학습 비용 감당 가능한 경우 | 빠른 실험, 배포 제약 없을 때 |
EAGLE-2가 speedup ratio 기준으로 가장 높지만, 이 수치는 MT-bench 환경의 temperature=0, 소규모 배치 조건이다. 운영 환경에서는 배치가 커지고 태스크가 혼합되면서 실제 speedup이 낮아진다.
Lookahead는 수락률이 낮지만 모델 추가나 학습이 전혀 필요 없다. 우선 실험해보고 싶을 때 먼저 써볼 만하다.
언제 쓰지 말아야 하는가
다음 조건 중 하나라도 해당하면 Speculative Decoding 도입 전에 다시 따져봐야 한다:
- 상시 배치 크기 8 이상인 서빙 환경 — throughput 관점에서 AR decode가 더 유리할 수 있다
- 주요 태스크의 수락률이 0.6 미만으로 예상되는 경우 (수학 추론, 한국어 자유 생성 등)
- GPU HBM 여유가 20% 미만 — draft model KV 캐시나 EAGLE head를 올릴 공간이 없으면 max 배치가 줄어 throughput 순 손해
이 중 배치 크기 조건이 가장 자주 간과된다. 벤치마크를 batch=1로 찍고 배포했다가 실제 트래픽에서 효과가 없거나 느려지는 케이스다.
vLLM에서 실험할 때는 배치 크기를 달리하며 tokens/s를 직접 측정하는 게 가장 확실하다:
# independent draft model 방식
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-2-70b-chat-hf \
--speculative-model facebook/opt-125m \
--num-speculative-tokens 4 \
--gpu-memory-utilization 0.85
# --num-speculative-tokens 4 vs 8을 바꿔가며 배치별 tokens/s 비교
--num-speculative-tokens 값을 4에서 8로 올리면 수락률이 높은 태스크(코드 완성)에서는 throughput이 더 올라가지만, 수락률이 낮은 태스크(수학 추론)에서는 draft overhead가 더 커져 오히려 손해다. 태스크 혼합 비율을 실제 트래픽과 맞춰서 측정해야 의미 있는 숫자가 나온다.