Unsloth DeepSeek V4는 정말 2배 빠를까? DGX Spark 두 대에서 확인해봤다
며칠 전 DeepSeek V4 Flash 공식 API와 DGX Spark 두 대의 로컬 모델을 비교했다. 로컬에서는 공식 checkpoint를 vLLM의 tensor parallel 2로 실행하고 DSpark speculative decoding을 사용하고 있었다.
그런데 Unsloth가 DeepSeek V4 Flash 0731의 lossless GGUF와 함께 “DSpark로 최대 2배 빠른 decoding”이라는 결과를 공개했다.[1][2] 처음에는 당연히 이런 생각이 들었다.
그러면 지금 쓰는 vLLM 대신 Unsloth GGUF로 바꾸면 두 배 빨라지는 걸까?
결론부터 말하면 아니다. DGX Spark에서도 DSpark는 실제로 llama.cpp의 출력 생성을 2배 이상 가속했다. 하지만 가속된 llama.cpp도 기존 vLLM보다 느렸다. 지금 운영 중인 공식 native checkpoint + vLLM TP=2 + DSpark 구성을 계속 쓰기로 했다.
이 글은 모든 측정값을 나열하는 보고서가 아니라, 테스트하면서 생긴 핵심 질문에 답하는 방식으로 정리했다.
“최대 2배”는 무엇보다 2배 빠르다는 뜻일까?
가장 먼저 확인해야 할 것은 비교의 분모였다. Unsloth의 공개 수치는 다음 비교다.[1]
같은 GGUF와 같은 llama.cpp에서
DSpark를 끈 target-only vs DSpark를 켠 상태
다음 비교가 아니다.
Unsloth GGUF + llama.cpp vs 공식 checkpoint + vLLM
이 차이를 분리하기 위해 같은 UD-Q8_K_XL GGUF, 같은 llama.cpp build, 같은 2노드 RPC 구성에서 drafter만 제거한 target-only 대조군을 다시 실행했다. 256-token 입력에서 한 요청의 decode 속도는 다음과 같았다.
| 같은 llama.cpp에서 비교 | decode 속도 |
|---|---|
| target-only | 11.13 tok/s |
| DSpark 사용 | 27.41 tok/s |
| DSpark 가속 | 2.46배 |
DSpark는 DGX Spark에서도 제대로 작동했다. 짧은 번역과 속도 측정 구간에서는 draft token의 88.6%가 실제 출력에 채택됐다. “같은 llama.cpp에서 DSpark가 decoding을 최대 2배가량 가속한다”는 방향은 오히려 우리가 측정한 결과에서도 분명하게 재현됐다.
그런데 왜 기존 vLLM보다 느렸을까?
DSpark가 가속하는 것은 target model이 한 token씩 생성하던 decode 구간이다. 출발점인 target runtime 자체가 느리거나, 입력을 읽는 prefill과 노드 간 통신이 병목이면 DSpark만으로 전체 성능을 역전하기 어렵다.
같은 256-token 입력과 단일 요청에서 세 구성을 놓고 보면 이유가 바로 드러난다.
| 실행 구성 | decode 속도 | 전체 completion 처리량 |
|---|---|---|
| Unsloth GGUF + llama.cpp target-only | 11.13 tok/s | 10.46 tok/s |
| Unsloth GGUF + llama.cpp + DSpark | 27.41 tok/s | 23.68 tok/s |
| 공식 checkpoint + vLLM + DSpark | 78.66 tok/s | 67.56 tok/s |
llama.cpp는 DSpark 덕분에 2배 이상 빨라졌지만, 빨라진 뒤의 decode 속도도 vLLM의 약 35%였다. 동시 요청 6개의 전체 completion 처리량도 vLLM 185.24 tok/s, llama.cpp DSpark 55.90 tok/s였다.
긴 입력에서는 차이가 더 커졌다. 131K-token 입력을 받은 뒤 첫 출력이 나오기까지 vLLM은 70.61초, llama.cpp DSpark는 467.56초가 걸렸다. 같은 llama.cpp에서 DSpark를 끈 경우도 472.26초였다. 이 구간에서는 speculative decoding이 손댈 수 있는 출력 생성보다 2노드 layer split RPC로 입력을 읽고 동기화하는 시간이 대부분이었다.
즉 이번 결과가 느린 이유는 DSpark가 작동하지 않아서가 아니라, UD-Q8_K_XL + llama.cpp 2노드 RPC target runtime의 절대 속도가 기존 vLLM TP=2보다 낮았기 때문이다.
번역처럼 답이 짧은 작업에서도 이득이 있을까?
이득은 있었지만 vLLM을 역전하지는 못했다. 같은 llama.cpp에서 DSpark를 켜면 제목 30개 번역은 91.07초에서 61.20초로, 문맥 단어 36개는 58.72초에서 48.89초로 줄었다.
| 번역 작업 | vLLM + DSpark | llama.cpp target-only | llama.cpp + DSpark |
|---|---|---|---|
| 제목 30개 | 24.21초 | 91.07초 | 61.20초 |
| 문맥 단어 36개 | 20.46초 | 58.72초 | 48.89초 |
제목 번역의 평균 출력은 24 tokens, 단어 번역은 11.4 tokens에 불과했다. speculative decoding이 가속할 출력 구간이 짧아, drafter를 실행하고 검증하는 비용을 회수할 시간이 많지 않다. 그래도 제목 번역에서는 target-only보다 1.49배 빨라졌으므로 DSpark가 아무 효과가 없었던 것은 아니다.
번역 품질도 한쪽이 무조건 우세하다고 말하기 어려웠다. Unsloth GGUF는 제목 30개 중 이전 공식 API 출력과 완전히 같은 항목이 21개로 vLLM의 18개보다 많았다. 반면 문맥 단어 기대 표현은 vLLM 33/36, Unsloth GGUF 31/36이었고 일본어 제목 하나는 번역하지 않은 채 그대로 반환했다. “lossless라서 출력이 항상 같다”거나 “GGUF라서 품질이 낮다”는 식으로 단순화할 결과는 아니었다.
코딩 에이전트 5개 과제에서는 vLLM이 3개, llama.cpp DSpark가 2개를 통과했다. 전체 실행 시간은 각각 2,267초와 9,903초였다. 과제가 다섯 개뿐이라 모델의 지능 차이를 일반화할 수는 없지만, 지금 운영 구성을 바꿀 이유를 찾지는 못했다.
Unsloth의 B200 결과는 왜 훨씬 빠를까?
Unsloth가 공개한 조건은 이번 DGX Spark 구성보다 GGUF 실행에 훨씬 유리하다.
| NVIDIA B200 | DGX Spark | |
|---|---|---|
| 메모리 | 180GB HBM3e | 128GB LPDDR5X 통합 메모리 |
| 메모리 대역폭 | 최대 8TB/s | 273GB/s |
| 공개 결과에 사용한 target | UD-Q4_K_XL |
이번 테스트는 lossless UD-Q8_K_XL |
출처: Unsloth[1], NVIDIA DGX Spark[4], NVIDIA B200[5]
Unsloth의 Q4 target과 drafter는 B200 한 장에 함께 들어간다. 반면 이번에 선택한 lossless Q8 main은 약 161.9GB, drafter는 약 10.9GB로 합계가 172.8GB였다. 128GB인 DGX Spark 한 대에는 들어가지 않아 두 대에 layer를 나누고 ConnectX-7 200GbE로 연결해야 했다.[1][2][4]
B200은 훨씬 높은 메모리 대역폭을 사용할 뿐 아니라, 한 장에 모델을 넣으면 노드 간 layer split 자체를 피할 수 있다. Unsloth 공개 표에서도 1× B200의 DSpark 결과가 119.7 tok/s, 4× B200 layer split은 112.4 tok/s였다.[1] GPU가 많다고 항상 이 구간이 빨라지는 것이 아니라, 모델을 한 장에 넣어 통신을 피하는 것이 더 중요할 수 있다는 사례다.
8TB/s와 273GB/s 같은 peak 사양을 그대로 실제 성능 배수로 읽어서는 안 된다. 다만 B200에서 나온 숫자를 2노드 DGX Spark에 그대로 기대하기 어려운 이유는 충분히 보여준다.
그렇다면 GGUF는 왜 공개하는 걸까?
GGUF의 목표를 “vLLM보다 더 빠른 파일”로 생각하면 이상해 보인다. 하지만 GGUF의 강점은 다른 곳에 있다.
- llama.cpp, Ollama, LM Studio, Unsloth Studio 같은 로컬 실행 생태계
- macOS, Windows, CPU, Metal, Vulkan 등 다양한 환경
- GPU 메모리가 부족할 때 CPU와 GPU에 나눠 올리는 offload
- 장비 메모리에 맞춘 여러 저비트 선택지
- 별도 serving cluster 없이 단일 파일 중심으로 배포하기 쉬운 형태
관련 문서: Unsloth[1]
Unsloth가 말하는 Q8 “lossless”도 tensor를 GGUF에 표현하는 방식에서 공식 weight를 보존했다는 뜻이다. vLLM과 llama.cpp의 kernel, scheduler, KV cache, chat template, speculative 구현과 분산 방식까지 같다는 뜻은 아니다. 따라서 lossless가 곧 같은 출력이나 같은 속도를 보장하지는 않는다.[1][2]
Unsloth GGUF를 vLLM에서 실행하면 빨라질까?
vLLM은 GGUF를 읽을 수 있지만, 그것만으로 기존 native checkpoint보다 빨라지는 것은 아니다. vLLM 공식 문서는 GGUF 지원을 현재 “highly experimental and under-optimized”라고 설명한다.[3] 반면 지금 쓰는 공식 checkpoint 경로는 DeepSeek V4의 native MXFP4 expert와 FP8/BF16 구성을 위한 kernel과 DSpark를 직접 사용한다.
이번에는 Unsloth GGUF + vLLM을 측정하지 않았으므로 성능 수치를 만들 수는 없다. 다만 GGUF를 vLLM에 넣는 것만으로 지금의 native vLLM 경로보다 빨라질 것이라고 기대할 근거도 없다. 별도의 native-format Unsloth checkpoint와 그 양자화를 최적화한 vLLM kernel이 나온다면 새로운 비교 대상이 될 수 있지만, 이번 GGUF 결과에서 그 성능을 추론해서는 안 된다.
그래서 무엇을 계속 사용할까?
현재 2× DGX Spark 운영 환경에서는 다음 구성을 유지한다.
공식 DeepSeek V4 Flash 0731 native checkpoint + vLLM TP=2 + DSpark
이 선택은 단순히 256-token decode 속도 하나만 본 결과가 아니다. 짧은 번역의 end-to-end 시간, 동시 요청 처리량, 긴 context의 첫 응답 시간, 코딩 에이전트 성공률을 함께 봤을 때 기존 구성이 모두 더 실용적이었다.
그렇다고 Unsloth 결과가 틀렸다는 뜻은 아니다. 같은 llama.cpp target에 DSpark를 켰을 때 2배가량 빨라졌고, 우리 DGX Spark에서도 그대로 확인했다. 다만 “llama.cpp가 2배 빨라졌다”와 “기존 vLLM보다 2배 빠르다”는 전혀 다른 문장이다.
한 대의 B200처럼 모델과 drafter를 모두 넣을 수 있는 장비, 또는 128GB 장비 한 대에 들어가는 저비트 GGUF가 목표라면 Unsloth의 선택지는 충분히 의미가 있다. 이번에 확인하고 싶었던 것은 lossless Q8 GGUF가 현재 2× DGX Spark 운영 구성을 대체할 수 있느냐였고, 그 답은 아직 아니다였다.
측정 범위
세 구성은 기준선에서 생성한 같은 frozen prompt를 사용했다. 속도 측정에서는 thinking을 끄고, 번역은 같은 30개 기술 제목과 36개 문맥 단어를 사용했다. 코딩 에이전트는 동일한 5개 과제와 20턴 제한으로 실행했다. 4,096-token 장문 출력은 llama.cpp target-only에서만 별도로 측정했으며 DSpark와의 직접 배수 비교에는 사용하지 않았다.
- [1] Unsloth: DeepSeek V4 로컬 실행과 DSpark 안내 (원문: DeepSeek-V4: How to Run Locally)
- [2] Hugging Face, Unsloth: DeepSeek V4 Flash 0731 GGUF (원문: unsloth/DeepSeek-V4-Flash-0731-GGUF)
- [3] vLLM: GGUF 지원 문서 (원문: GGUF)
- [4] NVIDIA: DGX Spark 하드웨어 개요 (원문: Hardware Overview — DGX Spark User Guide)
- [5] NVIDIA: B200 메모리와 대역폭 사양 (원문: Components — NVIDIA HGX AI Factory)