
vLLM의 서빙 스택을 C++20으로 포팅: Python 없이 66 MiB 바이너리, 추론 시 토큰별로 vLLM과 검증
요약
vLLM의 서빙 스택을 C++20으로 포팅하여 Python 의존성 없이 66 MiB의 경량 바이너리로 구현한 프로젝트를 소개합니다. 연속 배치 처리 및 추측 디코딩 등 핵심 기능을 포함하며, 기존 vLLM과 대등하거나 소폭 앞서는 성능을 보여줍니다.
핵심 포인트
- Python 없이 C++20으로 구현하여 66 MiB의 초경량 바이너리 제공
- vLLM과 토큰 단위 검증을 통해 동일한 출력 정확도 확보
- 연속 배치 처리, 블록 페이지 KV, 추측 디코딩 등 핵심 기능 지원
- 기존 vLLM 대비 동등하거나 소폭 높은 추론 성능 기록
- 메모리 점유 공간(Footprint)을 획기적으로 절감
제가 작성한 글이라 열정적인 부분은 감안해 주시기 바랍니다. 이 프로젝트는 vLLM 프로젝트와 무관하게 커뮤니티에서 포팅한 것이며, vLLM이 정확성을 검증하는 데 사용된 것입니다. 시작 계기는 다음과 같습니다. 저는 vLLM을 좋아하지만, 여기서 vLLM을 설치하려면 9.1 GiB의 virtualenv가 필요했고, 프로세스 내에 인터프리터를 갖는 것이 문제가 되는 기기에서 다른 소프트웨어 안에 추론 기능을 임베드하고 싶었습니다. 그리고 솔직히 말해서, Python 의존성은 보안(공급망 공격)과 Python 자체의 비대함 측면에서 배포 스토리가 다릅니다. 그래서 vllm.cpp는 C++20으로 처음부터 작성된 vLLM의 서빙 스택입니다. 아직 이름은 정해지지 않았으며, 더 나은 이름이 생길 때까지 vllm.cpp라고 부르고 있습니다. 연속 배치 처리(Continuous batching), 블록 페이지 KV(block-paged KV), 자동 접두사 캐싱(automatic prefix caching), 추측 디코딩(speculative decoding), 그리고 OpenAI와 호환되는 서버 기능을 갖추고 있습니다. Python이나 PyTorch 없이 66 MiB의 바이너리로 빌드됩니다. 크기보다 게이트가 저에게는 더 중요합니다. 모든 아키텍처는 동일한 워크로드에서 고정된 vLLM 오라클과 토큰별로 검사되며, 업스트림 자체 테스트 모듈도 코드와 같은 커밋에 포팅되었습니다. ID가 일치해야 합니다. 지금까지 25개 정도의 아키텍처를 다루었습니다. 그리고 네, 이 프로젝트는 AI를 광범위하게 사용합니다. 어떻게 구조화되었는지에 대한 후속 내용을 준비하고 있습니다 (이것은 포팅이며, MLX나 Radix Attention 지원 등 일부 부분에서 벗어납니다). 속도에 관해서는 가장 먼저 질문할 문제입니다. 이미지에서 볼 수 있듯이 고성능 동시성(high concurrency) 면에서 vLLM과 거의 대등합니다. 저는 DGX Spark, Thor, AGX Orin에서만 테스트했습니다. Qwen3.6-27B NVFP4 모델을 DGX Spark (GB10)에서 vLLM의 프로덕션 그래프 설정과 비교하여, 중간값(medians)은 3개 인터리브된 복제본, 1024 in / 128 out으로 테스트했습니다: 동시성 | vllm.cpp | vLLM | 비율
1 | 86.05 | 82.32 | 1.045x
2 | 159.68 | 158.03 | 1.011x
4 | 292.34 | 290.31 | 1.007x
8 | 508.77 | 505.46 | 1.007x
16 | 801.76 | 789.16 | 1.016x
32 | 1095.01 | 1076.25 | 1.017x 전반적으로 모든 면에서 근소하게 앞서지만, 실행마다의 노이즈는 0.5%이며 그중 다섯 개가 1.7% 이내에 있습니다. 즉, c1에서는 승리하고 나머지 다섯 개는 동률이라고 말하는 것이 더 정확할 것 같습니다.
모든 지점에서 출력이 동일합니다. 메모리는 덜 모호한 축입니다. vLLM은 사전에 고정된 비율을 예약하고 워크로드에 필요한 만큼 할당하므로, 피크 GPU 메모리는 40,996 MiB 대 70,531 MiB로 나타나지만, 이는 KV 캐시가 더 저렴해서라기보다 점유 공간 (footprint)의 차이입니다. 사람들이 보통 궁금해하는 다른 수치들은 다음과 같습니다: 동일한 GGUF 파일을 사용하여 CPU aarch64에서 llama.cpp의 프리필 (prefill) 대비 1.18배 성능을 보였으며 디코딩 (decode)은 동률이었고, M4에서의 MLX-LM 웜업 (warm) 총합 대비 97.6%를 기록했습니다. 또한, 하나의 Spark에서 2-bit GGUF로 구동되는 DeepSeek-V4-Flash는 18.69 tok/s를 기록했는데, 이는 제가 찾을 수 있었던 해당 모델의 가장 빠른 GGUF 엔진보다 1.14배 빠른 수치입니다. 투기적 디코딩 (Speculative decoding) 기능도 포함되어 있습니다: MTP는 c1의 속도를 9.97에서 15.10 tok/s로 높였고, DFlash는 10.16에서 29.32 tok/s로 높였으며, 두 경우 모두 동일한 투기자 (speculator)를 실행하는 vLLM보다 우위에 있습니다. 이 엔진은 safetensors와 GGUF를 로드하며, NVFP4, k-quants 및 i-quants, fp8, bf16을 지원합니다. CUDA sm_80부터 sm_121a까지, AVX-512 및 Arm i8mm를 지원하는 CPU, Metal, 그리고 부분적인 Vulkan을 지원합니다. 모델 목록은 여기에 붙여넣는 대신 리포지토리 (repo)에 포함되어 있습니다. 또한 sglang의 일부 요소와 radix attention 및 LPM 인지 캐시 스케줄링 (LPM aware cache scheduling) 같이 제가 C++ 엔진에서 항상 보고 싶었던 아이디어들도 포함되어 있습니다. 작동하지 않는 부분: 모델 아키텍처, 하드웨어 지원 등 많은 것들이 아직 구축되어야 하며, 실제 하드웨어에서의 멀티 GPU (multi-GPU)는 지원되지 않습니다 (CPU에서는 텐서 병렬 (tensor parallel)이 tp=1과 동일함이 증명되었습니다. 저는 장비가 하나뿐입니다). LoRA는 서버를 통해 연결되지 않았으며, 멀티모달 (multimodal)은 CLI와 라이브러리에서는 실행되지만 HTTP API를 통해서는 실행되지 않습니다. 임베딩 (embedding) 또는 리랭킹 (reranking) 모델도 없으며, ROCm도 지원하지 않습니다. 또한 현재 활발히 개발 중이므로 플래그 (flags)와 내부 구현이 커밋 (commit) 사이에 변경될 수 있습니다. 다만 버전 관리되는 C ABI라는 안정적인 인터페이스는 존재합니다. 새로운 아키텍처로의 포팅을 위한 커뮤니티의 도움을 환영합니다! 시작하려면 빌드 도구는 cmake뿐입니다:
cmake -S . -B build && cmake --build build -j # CPU
cmake -S . -B build-cuda -DVLLM_CPP_CUDA=ON -DVLLM_CPP_TRITON=ON # CUDA
cmake --build build-cuda -j
Apache 2.0. https://github.com/mudler/vllm.cpp
벤치마크, 방법론, 그리고 우리가 패배한 항목들: https://github.com/mudler/vllm.cpp/blob/main/docs/BENCHMARKS.md
무엇이든 기꺼이 답변해 드리겠습니다!
/u/mudler_it 님이 제출함 [link] [comments]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/LocalLLaMA의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기