RTX 5090 단일 카드: vLLM에서 262K 컨텍스트로 Qwen3.8-27B NVFP4 구동 — 짧은 컨텍스트 77 tok/s, 128K에서 64.7 tok/s
Single RTX 5090: Qwen3.8-27B NVFP4 at a real 262K context in vLLM — 77 tok/s short-context, 64.7 tok/s at 128K
핵심 요약
RTX 5090에서 262K 컨텍스트를 활용한 Qwen3.8-27B 모델의 구동 환경과 성능 측정 결과를 상세히 공유함.
성능 측정 — 262K 컨텍스트에서 64.7~77.2 tok/s의 디코드 속도 기록
하드웨어 최적화 — vLLM과 NVFP4 양자화를 통해 32GB VRAM 내에서 구동
프리픽스 캐싱 — 캐싱 적용 시 TTFT가 22배 이상 단축되는 효과 확인
설정 공유 — 실제 사용 중인 vLLM 실행 명령어와 챗 템플릿 상세 공개
이건 내가 RTX 5090 한 장으로 매일 실제로 쓰고 있는 Qwen3.8-27B 세팅이다.
다른 5090 유저들도 내가 어떤 메모리 설정을 썼는지 일일이 추측할 필요 없이 그대로 따라 할 수 있게 상세하게 적어두려고 한다.
요약하자면: 비전, FP8 KV, 프리픽스 캐싱, 툴 콜링, 그리고 일반적인 KDE 데스크톱 환경까지 다 띄워놓고 262,144 토큰 윈도우를 전부 돌릴 수 있다. 1K 프롬프트 입력 후 디코딩 속도는 77.2 tok/s고, 128K가 이미 올라가 있는 상태에선 64.7 tok/s가 나온다. 262,000 토큰 프리필은 166초 걸렸다. 262K가 빠르다는 소리가 아니라, 실제로 돌아가고 완주가 가능하다는 걸 증명하는 거다.
JonathanColetti/Qwen3.8-27B-Uncensored를 NVFP4 ModelOpt로 뽑아낸 버전이다. 체크포인트는 safetensors 기준 19.18 GiB고, 비전 타워랑 MTP 헤드도 그대로 살아있다. 이 모델은 64개 레이어 하이브리드 구조인데, Gated DeltaNet 레이어 48개랑 풀 어텐션 레이어 16개로 구성됨.
결과
모든 실행은 이미 예열된 vLLM 서버에 /v1/completions로 쐈고, 동시성 1, 랜덤 토큰 프롬프트, --ignore-eos, 온도 0으로 설정했다. PP는 TTFT로 나눈 입력 토큰 수. TG는 1000 / 평균_TPOT_ms라 프리필은 제외됨. 프리픽스 캐시를 안 쓴 실행들은 서버 카운터상 캐시 히트가 0이었다.
짧은 컨텍스트 디코딩은 평균 TPOT 12.959ms에 피크 속도 78 tok/s 찍혔다. 128K 컨텍스트가 상주할 때는 TPOT이 15.463ms로 올라가서 생성 속도가 약 16.2% 떨어진 64.7 tok/s가 나왔다.
128K랑 262K 행은 각각 한 번씩만 돌린 거다. 이건 분포도가 아니라 그냥 측정된 동작 지점 정도로 보면 된다. 8K, 32K, 그리고 짧은 컨텍스트 디코딩 행은 여러 번 돌린 결과값이다.
컨텍스트가 커질수록 PP가 떨어지는 폭이 꽤 큰데, 이건 완전한 선형 어텐션 모델이 아니라 하이브리드 모델이라 그렇다. 레이어 16개는 여전히 풀 어텐션을 쓰거든.
프리픽스 캐싱
공유 프리픽스 36,864 토큰, 고유 서픽스 16 토큰, 출력 토큰 1개, 순차 요청 5회로 새로 테스트함:
콜드 TTFT: 6.437 s
캐시된 TTFT 4회: 0.288, 0.282, 0.296, 0.288 s
캐시된 중앙값: 0.288 s
콜드 대비 캐시 속도 향상: 22.3배
예전 기록에는 6.61 -> 0.20초, 즉 33배라고 적어놨었는데, 이번 테스트에선 0.20초가 안 나와서 지금은 22.3배라고 하는 게 맞다. 프리픽스 캐싱은 긴 대화형 에이전트를 쓸 때 매번 전체 대화 내용을 다시 프리필하는 거랑 그냥 쓸 수 있는 거 사이의 차이를 만든다.
중요한 주의사항: vLLM은 프리픽스 캐싱을 켜면 하이브리드 Mamba/DeltaNet 캐시를 실험적인 align 모드로 돌린다. 만약 출력값이 깨져서 나오면 프리픽스 캐싱부터 끄는 게 제일 먼저 해볼 테스트다.
하드웨어 및 소프트웨어
Part
Exact measured setup
GPU
NVIDIA GeForce RTX 5090, 32,607 MiB reported VRAM, 600 W power limit
CPU
Intel Core i7-14700K, 20 cores / 28 threads
RAM
32 GiB installed, 31 GiB visible
OS
Arch Linux, kernel 7.1.8-arch1-3
Desktop
KDE/Wayland, with Firefox and terminals open during the VRAM snapshots
NVIDIA driver
610.57.04 (nvidia-open / nvidia-utils 610.57.04)
CUDA toolkit
Arch cuda 13.3.1-1, nvcc 13.3.73
Python
3.13.13
vLLM
0.27.1, release wheel
PyTorch
2.13.0+cu130
Transformers
5.15.0
FlashInfer
0.6.16.post3
Triton
3.7.1
compressed-tensors
0.17.0
런타임은 시작 로그에서 다음 경로들을 자동으로 선택했다:
modelopt_fp4 양자화
FlashInfer CUTLASS NVFP4 GEMM
텍스트 모델용 FlashInfer 어텐션, SM120에서 flashinfer-native 디코딩
Triton/FLA GDN 프리필 커널
비전 인코더용 Flash Attention
전체 및 부분 CUDA 그래프; 추론(speculation)은 끔
실제 VRAM 예산
모델 가중치 크기, vLLM 프로세스 할당량, 그리고 nvidia-smi에 찍히는 카드 전체 사용량 사이의 차이를 아는 게 중요하다.
Item
Measured
Checkpoint safetensors on disk
19.18 GiB
Model load reported by vLLM
18.51 GiB
Manually pinned KV pool
9,150,000,000 bytes = 8.52 GiB
GPU KV capacity reported by vLLM
268,170 tokens
Maximum 262,144-token concurrency reported by vLLM
1.02x
Live VLLM::EngineCore process
29,322 MiB
Final whole-card snapshot
30,532 MiB used / 1,610 MiB free
서버를 띄워놓고 유휴 상태일 때 스냅샷을 찍어보면, 데스크톱 환경 변화에 따라 남는 VRAM이 1,610에서 1,818 MiB 사이를 왔다 갔다 한다. 이게 실제 여유분인데, 아주 넉넉한 건 아니다. 헤드리스(모니터 없는) 환경 전용이라고 할 정도는 아니고, KDE, 파이어폭스, 터미널 다 띄워놓고 쓸 순 있지만, 여기서 무거운 CUDA 작업 하나 더 돌리면 당연히 터진다.
--gpu-memory-utilization 0.92는 이 설정에선 그냥 시작할 때 통과용 관문일 뿐이다. --kv-cache-memory-bytes 9150000000으로 KV 풀을 고정해버려서, vLLM은 이 할당량이 gpu_memory_utilization 설정을 무시한다고 명시한다. 0.92를 낮춘다고 KV 풀이나 컨텍스트 윈도우가 줄어들지 않는다. 그냥 일반적인 데스크톱 VRAM 점유 상태에서 프로세스가 시작되게 해줄 뿐이다.
--max-num-seqs 3이라고 해서 262K짜리 요청을 동시에 3개 돌린다는 뜻이 아니다. KV 풀은 전체 윈도우 용량의 1.02배밖에 안 되거든. 슬롯 3개는 같은 풀을 공유하는 더 짧은 실제 요청들을 처리할 때 도움을 주는 용도다.
정확한 설치 및 모델 리비전
난 이미 Arch NVIDIA 드라이버랑 /opt/cuda가 제대로 세팅된 상태였음. 아래 명령어는 위에서 쓴 파이썬 환경을 만들고 CUDA 13.0 vLLM/PyTorch 휠 버전을 고정하는 과정임:
추론(speculation) 기능을 안 쓴다고 해서 이 리비전에서 model-mtp-grafted.safetensors를 지우지 마라. 체크포인트 인덱스에 얘랑 매핑된 텐서가 15개나 들어있거든. 추론 기능을 끄면 vLLM이 런타임에 MTP 헤드를 건너뛰긴 하지만, 다운로드한 리비전을 그대로 둬야 체크포인트가 깨지는 일을 막을 수 있음.
내 데일리 세팅에서 쓰는 챗 템플릿
속도 테스트는 raw completions 엔드포인트를 쓰니까 챗 템플릿이 결과값에 영향을 주진 않음. 근데 내 평소 채팅이나 툴 사용 방식에는 영향을 주지.
내가 쓰는 정확한 템플릿은 froggeric/Qwen-Fixed-Chat-Templates v22.2 리비전 f64494d7b8a768222ab799d8c81f6e89dd272ac3에다가 시스템 프롬프트 간결화 블록을 살짝 추가한 거임. 원본 저장소는 그사이에 업데이트됐으니까 꼭 리비전을 고정해서 써라:
첫 줄 버전 문자열을 qwen3.8-froggeric-v22.2-sharp로 바꾸고, {%- set _msgs = messages[head.count:] %} 바로 뒤에 이걸 넣었음:
{%- set _terse %}
Answer directly, after thinking. Lead with the answer, then only what it needs to be correct and usable.
Never: open with preamble or pleasantries; restate the question; add filler transitions; hedge with niceties; or repeat a point you've already made.
Always: keep essential steps, caveats, uncertainties, and specifics — never drop correctness or a needed warning for brevity. Keep the final answer lean. Use the least structure that conveys it (plain prose when short; lists or code only when they earn their place). If genuinely uncertain, say so and explain why — never omit uncertainty for the sake of brevity.
If a user request is genuinely ambiguous, ask a sharp question, don't guess.
{%- endset %}
{%- if not _sc %}
{%- set _sc = _terse | trim %}
{%- else %}
{%- set _sc = (_sc | trim) ~ '
' ~ (_terse | trim) %}
{%- endif %}
체크섬:
55d027bfded4407d214e5718e2f2804de73e8439148297397655ff507a30f2a5 froggeric v22.2 base
34dd122439410ee026562207c87124cb843ad92069568a9ab2f02e6d20626fea my sharp-v22.2 result
내 스타일 블록이 필요 없으면 그냥 고정된 Froggeric v22.2 파일을 그대로 쓰면 됨. 모델 기본 템플릿도 TEMPLATE=stock으로 돌리면 작동은 하는데, 내가 매일 쓰는 세팅이랑은 좀 다름.
실제 서버 실행 명령어
이게 실제 프로세스에서 돌아가는 명령어임. 경로는 바꿀 수 있는데, 값들은 위 결과값 뽑을 때 쓴 거 그대로임.
양자화랑 어텐션 백엔드는 그냥 auto로 뒀음. vLLM이 알아서 modelopt_fp4랑 FlashInfer를 잘 잡아주거든. 테스트할 때 플래그를 명시적으로 넣어도 되긴 하는데, 그럼 내가 측정한 수치랑 똑같은 환경이라고 보긴 어렵겠지.
보안 주의사항: --host 0.0.0.0으로 설정하면 인증 안 거치는 OpenAI 호환 엔드포인트가 외부로 다 노출됨. 난 신뢰할 수 있는 내부망(LAN)이라 일부러 이렇게 쓴 거니까, 외부망이라면 127.0.0.1로 바꾸거나 방화벽을 쓰든가, 아니면 vLLM의 API-key 옵션을 꼭 쓰도록 해.
왜 이런 수치들을 썼냐면:
9150000000 KV 바이트: 8,939,000,000 바이트로 설정했더니 288 토큰이 모자라더라고. vLLM이 최대 261,856 토큰으로 계산해서 262,144 길이 설정을 거부했거든. 지금 설정값은 268,170 토큰까지 수용 가능함.
--max-num-batched-tokens 512: 이건 여유 메모리를 확보하려고 둔 거야. 이걸 올리면 프리필(prefill) 성능은 좋아지는데 VRAM을 그만큼 잡아먹음.
--mm-processor-kwargs '{"max_pixels": 4014080}': 내가 측정했을 때 큰 이미지는 대략 3,908 토큰 정도로 제한되더라. tokenizer.json에 "truncation": null이 있는지 꼭 확인해. 예전 내보내기 파일에 max_length: 2048이 박혀 있으면 큰 이미지 처리할 때 HTTP 400 에러 뜸.
/opt/cuda/bin/nvcc가 보여야 함. CUDA가 /opt/cuda에 깔려 있는데 CUDA_HOME 설정이 안 되어 있으면 FlashInfer JIT가 맛탱이 감.
추론 디코딩(Speculative decoding): 왜 꺼놨나
기본값은 일부러 SPEC=off로 해놨음.
베이스 체크포인트용으로 학습된 외부 DSpark/dflash 드래프터가 이번에 abliterated(제거된) ModelOpt 내보내기 파일이랑 호환이 안 됨. 로더가 텐서 차원 불일치(128 vs 256) 때문에 뻗어버리거든.
내장 MTP 헤드는 로드되긴 하는데, 오히려 체크포인트 속도가 느려짐. 예전에 테스트해 본 결과는 이래:
Mode
Decode
Speculation off
78.55 tok/s
Built-in MTP, 1 token
58.41 tok/s, 78.7% acceptance
Built-in MTP, 3 tokens
45.02 tok/s, 57.9% acceptance
이식된 MTP 헤드는 BF16이라 타겟 모델의 NVFP4 커널을 못 써. 게다가 MTP는 KV 풀이 더 커야 함. 추론 토큰 1개당 최소 9.75e9 바이트, 3개면 1.005e10 바이트 정도 필요해. --max-num-batched-tokens 8192로 3토큰 MTP 돌리니까 262K에서 OOM(메모리 부족) 나더라. 그냥 추론 안 쓰고 깔끔하고 빠르게 돌리는 게 나음.
정확도/품질 관련 주의사항
이 글은 모델 품질이 아니라 모델 적합성이랑 서빙 속도 측정하는 글임. vLLM에서 이 체크포인트가 보정된 FP8 KV q/prob 스케일링을 제공하지 않고 스케일 1.0을 쓴다고 경고하는데, 이게 정확도에 영향을 줄 수도 있음. 난 여기서 정확도 차이까지는 정량적으로 안 따졌어. 하이브리드 캐시에서의 프리픽스 캐싱도 vLLM에서 실험적 기능이라고 박아놨고. 사실 tok/s 수치 소수점 한 자리 더 따지는 것보다 이런 주의사항들이 훨씬 중요함.
혹시 다른 5090 유저가 이거 똑같이 해볼 수 있으면, 128K PP/TG 성능이나 헤드리스 세션이랑 데스크톱 환경에서의 가용 VRAM 차이, 그리고 긴 문맥 검색에서 FP8-KV 품질 저하가 눈에 띄는지 꼭 비교해보고 싶음.
AI 사용 고지: 이 기기, 런처 설정, 실패한 실험들, 그리고 측정값들은 전부 내 거임. Codex를 써서 실시간 프로세스를 확인하고, 명시된 로컬 벤치마크를 돌리고, 저장된 JSON/텔레메트리 데이터를 검증하고, 이 글을 정리했음. 수치 관련 내용은 원본 출력값과 대조해서 직접 검토했고, LLM이 벤치마크 숫자를 생성하거나 추정하게 한 건 하나도 없음.
주요 댓글
r/localllama
5090을 활용한 Qwen3.8-27B 모델의 고성능 컨텍스트 처리 결과에 대해 사용자들은 놀라움을 표하며, 구체적인 설정 방법과 speculative decoding 호환성 문제에 대해 활발히 토론하고 있다.
58
소설을 세 편은 쓰셨네요. 근데 제 결론은 NVFP4 양자화치고는 너무 느린 것 같다는 겁니다.
3
MTP를 꺼놔서 그런 거임. 내 생각엔 체크포인트랑 호환이 안 되는 듯.
-17
틀렸음. 컨텍스트 크기 생각하면 꽤 괜찮은 거임.
14
내 5090은 160K 깊이에서 평균 100tps 넘게 나오고, 같은 깊이에서 프리필 2200tps 나오는데 Q6_K 양자화 썼거든. 뭐, 네 말이 맞다고 치자... 난 그냥 '틀린' 상태로 있을게.
35
AI 쓰레기 글이네.
5090 NVFP4면 150~200 t/s는 나와야 정상임.
1
맞음. 나도 오픈박스로 산 1.2k짜리 r9700으로 작성자가 말한 거 똑같이 할 수 있음.