
1x/2x RTX 5090에서 Unsloth의 Qwen3.6-27B NVFP4 벤치마크 수행: MTP는 매우 훌륭하지만 한계가 있습니다.
요약
Unsloth의 Qwen3.6-27B NVFP4 모델을 RTX 5090 환경에서 벤치마크한 결과입니다. MTP(Multi-Token Prediction) 설정 시 단일 사용자 환경에서는 속도가 크게 향상되지만, 배치 작업이나 긴 컨텍스트에서는 성능 저하가 발생할 수 있음을 확인했습니다.
핵심 포인트
- nspec=3 설정 시 단일 GPU에서 생성 속도가 약 82% 향상됨
- MTP 사용 시 GPU 개수를 늘리는 것보다 단일 GPU 효율이 더 높을 수 있음
- 컨텍스트가 커지거나 동시성이 높아지면 MTP의 이점이 사라지고 속도가 저하됨
- RTX 5090 2개를 사용한 Tensor Parallel 방식보다 단일 GPU MTP가 더 빠른 결과 도출
저는 한동안 Qwen3.6-27B의 GGUF 버전을 사용해 왔기에, Unsloth에서 NVFP4 버전을 출시했을 때 vLLM에서 어떤 성능을 보여줄지 확인해보고 싶었습니다. 혼동을 피하기 위해 말씀드리자면, 이것은 Unsloth의 Qwen3.6-27B NVFP4 릴리스이며, NVIDIA의 별도 NVFP4 릴리스가 아닙니다. 제가 가장 알고 싶었던 핵심은 num_speculative_tokens를 어떻게 설정하느냐였습니다. 또한 모델을 두 개의 5090에 분산하는 것이 실제로 생성 속도에 도움이 되는지, 그리고 동시성 (concurrency)이나 큰 컨텍스트 (context)를 추가했을 때 MTP가 여전히 잘 작동하는지도 알고 싶었습니다. 짧은 답변을 드리자면: nspec=3은 짧은 컨텍스트를 사용하는 단일 사용자에게 매우 좋습니다. 하지만 GPU가 배치 (batching) 작업으로 바빠지거나 컨텍스트가 커지면, 이점은 대부분 사라지며 오히려 상당히 심각한 속도 저하로 이어질 수 있습니다. https://preview.redd.it/dht5v418ileh1.png?width=2400&format=png&auto=webp&s=f4517815a4db1324b2ba16a4c5bf27ff1c0364aa
모델 설정: Unsloth Qwen3.6-27B-NVFP4 (compressed-tensors; NVFP4 MLP, FP8 attention)
GPU: 2x RTX 5090, 각각 32 GB
vLLM: 0.25.1
PyTorch: 2.11.0+cu130
Driver: 580.159.03
Attention backend: TRITON_ATTN
최대 모델 길이: 65,536
1 GPU: tensor_parallel_size=1, max_num_seqs=16
2 GPUs: tensor_parallel_size=2, max_num_seqs=32
MTP 방식: qwen3_5_mtp
MTP 및 동시성 테스트를 위해, 저는 "100까지 세어보세요"와 같은 합성 프롬프트 (synthetic prompt) 대신 Spec-Bench 프롬프트 데이터셋을 사용했습니다.
단일 요청 테스트: 24개 프롬프트, 512개 요청 출력 토큰 (output tokens)
동시성 테스트: 256개 출력 토큰, 동시성 1/4/8/12/16에서 8/16/32/48/64개 프롬프트 사용
컨텍스트 테스트: 컨텍스트 크기당 4개의 고정 길이 랜덤 프롬프트, 256개 출력 토큰
컨텍스트 샘플이 적기 때문에, 이 수치들을 보편적인 법칙이 아닌 이 설정에 대한 강력한 신호로 간주하겠습니다. 샘플링은 모델 기본값인 temperature=1.0, top_k=20, top_p=0.95로 두었습니다. 이는 정확한 수락률 (acceptance rate)과 MTP 속도가 실행마다 달라질 수 있음을 의미합니다. 섹션 1과 3에서 디코드 속도 (decode speed)는 1000 / 중앙값 TPOT 입니다. 일반적인 언어로 표현하자면, 이는 프롬프트 처리 (prompt processing)를 제외한 첫 번째 토큰 이후의 생성 속도를 의미합니다.
섹션 2는 다릅니다. 여기서는 모든 활성 요청(active request)에 걸친 전체 서버의 결합 출력 처리량(combined output throughput)을 보고합니다.
- MTP를 사용한 GPU 1개가 GPU 2개보다 더 빨랐습니다.
| GPU | MTP | Decode tok/s | 동일 GPU 기준 대비 변화 |
|---|---|---|---|
| 1x 5090 | off | 66 | baseline |
| 1x 5090 | nspec=3 | 120 | +82% |
| 2x 5090 | off | 99 | baseline |
| 2x 5090 | nspec=3 | 108 | +9% |
이것은 저를 놀라게 한 첫 번째 결과였습니다. nspec=3을 설정한 5090 1개는 120 tok/s에 도달한 반면, 동일한 MTP 설정을 사용한 5090 2개는 108 tok/s에 도달했습니다. 이것이 두 번째 카드가 무용하다는 의미는 아닙니다. 두 번째 카드는 KV 캐시(KV cache), 컨텍스트(context), 배치(batching) 및 프리필(prefill)을 위한 훨씬 더 많은 여유 공간을 제공합니다. 단지 이 테스트에서는 단일 요청 디코드(decode) 속도에 도움이 되지 않았을 뿐입니다. 제 추측으로는 텐서 병렬(tensor-parallel) 통신 비용이 MTP 트레이드오프(tradeoff)를 상당히 변화시키는 것 같습니다. TP=2(Tensor Parallelism 2)에서는 실행 간 변동(run-to-run movement)도 더 심했습니다. 이전 실행에서는 GPU 1개에서 117 tok/s, 2개에서 118 tok/s가 나왔습니다. GPU 1개 결과는 매우 일관적이었으나, GPU 2개 결과는 그렇지 않았습니다. 따라서 108이라는 수치를 모든 사람이 기대해야 하는 고정된 값으로 취급하지는 않겠습니다.
- 배치(batching)가 주도권을 잡으면 MTP는 무너집니다.
다음은 RTX 5090 1개에서의 총 서버 출력 토큰/초(total server output tokens per second)입니다. 이 수치는 각 개별 사용자가 보는 것이 아니라, 모든 활성 요청에 대해 결합된 수치입니다.
| 동시 요청 수 (Concurrent requests) | MTP off | nspec=3 | 변화 |
|---|---|---|---|
| 1 | 64 | 121 | +87% |
| 4 | 228 | 414 | +81% |
| 8 | 453 | 475 | +5% |
| 12 | 638 | 501 | -22% |
| 16 | 789 | 498 | -37% |
요청이 1개일 때 MTP는 처리량을 거의 두 배로 늘렸습니다. 요청이 8개일 때는 도움이 거의 되지 않았습니다. 요청이 12개와 16개일 때는 오히려 서버를 더 느리게 만들었습니다. 흥미로운 점은 부하(load) 상황에서도 수락률(acceptance)이 무너지지 않았다는 것입니다. 동시성 1일 때 약 73%였고, 동시성 16일 때 71%였습니다. 제 해석은 일반적인 배치(batching)가 이미 GPU를 바쁘게 유지하고 있기 때문에, 투기적 검증(speculative verification)이 더 이상 스스로를 정당화할 만큼 충분한 디코드 단계(decode steps)를 절약하지 못하는 추가 작업이 되어버린다는 것입니다. 여기서 이상한 점은 동시성 4입니다. 이번 실행에서는 MTP로 414 tok/s를 측정했지만, 이전 실행에서는 250 tok/s만 측정되었고 꼬리 지연 시간(tail latency)이 매우 심했습니다. 기준 수치(baseline numbers)와 동시성 1/8/12/16의 동작은 상당히 밀접하게 재현되었습니다.
동시성(concurrency) 4에서 나타난 +81%라는 수치를 전적으로 신뢰하기 전에는 더 많은 반복 테스트가 필요할 것 같습니다. 3. 긴 문맥(Long context)은 결국 MTP를 더 빠른 방식에서 더 느린 방식으로 뒤집어 놓습니다.
RTX 5090 1개, 활성 요청 1개
입력 길이 | MTP off | nspec=3 | 변화량
2k | 66 | 107 | +62%
8k | 65 | 100 | +54%
32k | 61 | 62 | +2%
60k | 57 | 46 | -20%
텐서 병렬화(tensor parallelism)를 적용한 RTX 5090 2개, 활성 요청 1개
입력 길이 | MTP off | nspec=3 | 변화량
2k | 99 | 105 | +6%
8k | 96 | 117 | +22%
32k | 89 | 72 | -19%
60k | 81 | 45 | -44%
교차 지점(crossover)은 GPU 설정에 따라 달랐습니다. GPU 1개를 사용할 때는 32k에서 MTP가 거의 대등했고, 60k에서는 20% 더 느렸습니다. TP=2(텐서 병렬화 2)인 경우에는 이미 32k에서 19% 더 느렸고, 60k에서는 44% 더 느렸습니다. GPU 2개를 사용할 경우, 수락률(acceptance rate)은 8k에서의 약 71%에서 60k에서의 60%로 떨어졌습니다. 동시에, KV 캐시(KV cache)가 커짐에 따라 모든 검증 단계(verification pass)의 비용이 증가합니다. 이러한 조합이 이점을 매우 빠르게 상쇄시키는 것으로 보입니다.
따라서 "16k 이후에는 항상 MTP를 비활성화하라"와 같은 일반적인 규칙을 적용하지는 않겠습니다. 이 머신에서 교차 지점은 TP=2일 때 8k와 32k 사이였으며, GPU 1개일 때는 32k와 60k 사이였습니다. 사용자의 프롬프트와 수락률에 따라 이 지점은 변할 것입니다.
제가 현재 실제로 사용하고 있는 방식:
- 짧은 문맥을 사용하는 인터랙티브 사용자 1명: num_speculative_tokens=3
- 약 8개의 동시 요청: 두 방식 모두 테스트; 여기서 MTP는 단 +5%의 이점만 있었습니다.
- 5090 1개에서 12개 이상의 동시 요청: MTP off
- TP=2를 사용하는 32k 문맥: MTP off
- 어떤 설정이든 60k 문맥: MTP off
더 넓은 범위의 테스트(sweep)에서 얻은 추가 경고: 동시성 16에서 nspec=8과 TP=2를 사용했을 때, vLLM 서버가 CUDA error: an illegal memory access was encountered 오류와 함께 두 번 충돌했습니다. 이는 정확히 이 모델/백엔드 조합에서 2번의 시도 중 2번 모두 발생한 결과입니다. nspec=8이 모든 곳에서 고장 났다고 주장하는 것은 아닙니다.
빠른 품질 검증(quality sanity check)
양자화된 모델(quantized model)이 흥미로운 작업을 수행할 수 없다면 벤치마크 수치는 별로 유용하지 않으므로, 제가 개인용으로 만든 데스크톱 앱에서 에이전트 작업(agentic task)을 하나 시켜보았습니다: "Flappy Bird를 만들어줘." 추가 프롬프트도, 수정도, 힌트도 없었습니다. 모델은 작업을 계획하고, 코드를 작성했으며, 단 한 번의 패스(one pass)로 작동하는 게임을 실행했습니다.
https://reddit.com/link/1v2l1zi/video/lfslklsukleh1/player 분명히 말하지만, 단 한 번의 성공적인 데모가 품질 벤치마크(quality benchmark)가 될 수는 없으며, BF16 또는 GGUF 버전과 동등함을 증명하는 것도 아닙니다. 저는 단지 이 모델이 상당히 복잡한 에이전트 워크플로우(agentic workflow)에서도 여전히 사용 가능하다는 것을 확인하기 위한 건전성 검사(sanity check) 용도로 이를 포함했습니다.
재현 명령어(Reproduction command)
다음은 1-GPU nspec=3 서버 설정입니다:
vllm serve /path/to/Qwen3.6-27B-NVFP4
--served-model-name qwen
--tensor-parallel-size 1
--attention-backend TRITON_ATTN
--max-model-len 65536
--gpu-memory-utilization 0.90
--max-num-seqs 16
--reasoning-parser qwen3
--speculative-config '{"method":"qwen3_5_mtp","num_speculative_tokens":3}'
그리고 이것은 단일 요청 Spec-Bench 클라이언트입니다:
vllm bench serve
--backend openai-chat
--endpoint /v1/chat/completions
--model /path/to/model
--served-model-name qwen
--tokenizer /path/to/model
--dataset-name spec_bench
--dataset-path spec_bench_question.jsonl
--spec-bench-output-len 512
--num-prompts 24
--max-concurrency 1
--ignore-eos
--percentile-metrics ttft,tpot,itl,e2el
다른 분들 중에서도 두 개의 5090에서 이 Unsloth 릴리스를 테스트해 보신 분이 계신가요? 약한 TP=2 MTP 스케일링(scaling) 현상이 다른 어텐션 백엔드(attention backend)에서도 재현되는지 궁금합니다. 또한 결정론적 샘플링(deterministic sampling)과 더 많은 프롬프트를 사용하여 롱 컨텍스트 스윕(long-context sweep)을 반복해 보고 싶습니다.
제출자: /u/luke_pacman [link] [comments]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/LocalLLaMA의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기