tiny-vllm: C++와 CUDA로 vLLM을 직접 구현하며 배우는 LLM 추론 엔진
tiny-vllm: C++와 CUDA로 vLLM을 직접 구현하며 배우는 LLM 추론 엔진
개요
- 출처: PyTorchKR (discuss.pytorch.kr), 2026.06.01
- 작성자: 9bow (박정환) — GPT 모델로 정리한 글 바탕으로 작성
- 게시판: 읽을거리&정보공유
- 태그: llm-inference, vllm, cuda, kv-cache, pagedattention, gqa, tiny-vllm
- 원저자: Jędrzej Maczan (GitHub: jmaczan)
- 라이선스: Apache License 2.0
- 분류: LLM 추론 엔진, CUDA 프로그래밍, 교육 자료
내용 분석
프로젝트 개요
목적: 학습 도구 / 대학 강의 자료 구성: 실제 동작하는 추론 서버 전체 소스 코드 + 단계별 안내 코스(course) 글 범위: 학습(training) 아님, 추론(inference)만 다룸. Llama 3.2 1B Instruct 모델을 NVIDIA GPU 위에서 여러 요청을 병렬로 빠르게 실행하는 프로그램 직접 제작.
핵심 개념: 추론 서버(inference server)는 학습이 끝난 모델 가중치 파일을 실행해 프롬프트에 대한 응답을 만들어 내는 프로그램. LLM의 연산은 대부분 행렬 곱이므로 GPU에서 직접 코드를 돌리는 CUDA가 유리함.
추론 엔진의 구성 요소
- Safetensors 모델 로딩: Safetensors 포맷으로 저장된 Llama 3.2 1B Instruct 가중치 읽기
- 전체 forward pass: 프리필(prefill) + 디코드(decode) 모두 구현
- CUDA 커널화: 임베딩 조회, 정규화, 어텐션 등 핵심 연산을 직접 작성한 CUDA 커널로 수행
- KV 캐시: 이미 계산한 키와 값을 재사용해 디코드 단계의 중복 계산 줄임
- 정적 배칭 / 연속 배칭: 여러 요청을 묶어 처리량 높이는 두 가지 방식
- 온라인 softmax: FlashAttention 계열 방식으로 softmax를 점진적으로 계산
- PagedAttention: 운영체제의 페이징 아이디어를 KV 캐시 메모리 관리에 적용
주의: 코스 본문은 핵심 forward pass(임베딩부터 argmax까지)까지 상세하게 작성되어 있지만, 배칭과 온라인 softmax, PagedAttention을 다루는 뒤쪽 장은 아직 TODO 상태.
forward pass 동작 방식
Llama 3.2 1B 구조: 16개 트랜스포머 레이어
데이터 흐름:
- 텍스트 → 토큰 분할 → 임베딩 벡터 조회 (토큰 5개 입력 시 (5, 2048) 행렬)
- 16개 트랜스포머 레이어 통과 (각 레이어: RMSNorm → 잔차 연결 → 마스크드 GQA → 피드포워드 네트워크)
- 최종 RMSNorm → 선형 출력(lm_head) → argmax로 가장 확률이 높은 토큰 선택
그룹 쿼리 어텐션(GQA): 어텐션은 O(n²·d) 계산 복잡도를 갖는 비싼 연산. 쿼리 프로젝션(q_proj)은 출력 차원 2048인 반면 키/값 프로젝션(k_proj, v_proj)은 512로 더 작음. 여러 쿼리 헤드가 더 적은 수의 키/값 헤드를 공유해 KV 캐시 크기 줄임.
CUDA 커널 구현 예: RMSNorm
학습 가치: 추상적인 설명이 아니라 실제로 돌아가는 CUDA 커널을 직접 보여줌.
RMSNorm은 GPU에서 병렬 리덕션(parallel reduction)으로 구현. 공유 메모리(__shared__)에 제곱 합을 모은 뒤 트리 리덕션으로 합산하고, 그 결과로 입력을 정규화하는 과정이 한 커널 안에 담김.
코스에서 직접 작성하는 커널 목록: RMSNorm, RoPE, 잔차 연결, SiLU, softmax
BF16 포맷: 16비트 안에서 부호 1비트, 지수 8비트, 가수 7비트. 16비트 크기를 유지하면서도 32비트 float와 같은 8비트 지수를 가져 오버플로/언더플로 위험이 작아 추론에서 널리 쓰임.
실전 문제: cuBLAS의 cublasGemmEx는 열 우선(column-major) 메모리 레이아웃을 가정하는데, C/C++ 배열은 행 우선(row-major). tiny-vllm은 전치(transposition) 트릭으로 해결.
설치 및 실행 환경
- Linux (커널 6.19.8 x86_64)
- CUDA Toolkit 13.1
- C++ 17, GCC 15.2.1
- NVIDIA GPU (테스트 기준 RTX 5090), AMD CPU (Ryzen 7 9800X3D)
- Llama 3.2 1B Instruct의 model.safetensors 파일
- 외부 의존성: nlohmann/json 3.12.0 하나뿐 (단일 헤더 파일 포함)
더 읽어보기 (관련 글)
- Nano-vLLM (1200줄 경량 구현체)
- Nano-vLLM 내부 살펴보기 1, 2부
- Mini-SGLang
- TokenSpeed
- FlashKDA
---
새로운 시각
"밑바닥부터 구현"의 교육적 가치
vLLM, SGLang 같은 고성능 추론 엔진을 "사용"하는 것과 "이해"하는 것의 간극이 큽니다. tiny-vllm은 그 간극을 메우는 교육 도구입니다. CUDA 커널을 직접 작성하게 함으로써:
- KV 캐시가 왜 필요한지: 디코드 단계에서 이전 토큰의 키/값을 다시 계산하지 않는 이유를亲手體驗
- PagedAttention이 왜 빠른지: 운영체제의 가상 메모리 페이징이 GPU 메모리 관리에 어떻게 적용되는지 이해
- GQA의 트레이드오프: KV 캐시 크기를 줄이면서 정확도를 얼마나 희생하는지 확인
"학습 아님, 추론만"의 전략적 선택
학습과 추론을 분리한 것은 현명한 선택입니다. 학습은 역전파, 옵티마이저, 분산 학습 등 완전히 다른 복잡도 영역입니다. 추론만 집중하면:
- GPU 메모리 관리 (KV 캐시, PagedAttention)
- 배치 처리 (정적 배칭, 연속 배칭)
- 커널 최적화 (RMSNorm, RoPE, 어텐션)
이라는 추론 특화 기술을 집중 학습할 수 있습니다.
"GPT로 정리한 글"의 메타적 의미
이 글 자체가 AI로 정리된 것입니다. 원문(GitHub README + 코스 글)을 GPT 모델로 요약하고, PyTorchKR에 게시한 과정이 "AI로 학습 자료 만들기"의 실제 사례입니다. 다만 작성자가 "원문도 함께 참고해주세요"라고 경고한 것은 AI 요약의 한계를 인지하고 있는 태도입니다.
---
미래 영향
개발자 교육에 주는 시사점
- LLM 추론 엔진 이해 = AI 시대의 리터러시: 단순히 API를 호출하는 수준을 넘어, 내부 구조를 이해하는 개발자와 그렇지 않은 개발자의 격차가 커질 것
- CUDA 프로그래밍의 부활: LLM 추론 최적화를 위해 CUDA 커널 작성 능력이 다시 중요해짐
- 오픈소스 교육 자료의 가치: tiny-vllm, Nano-vLLM, Mini-SGLang 같은 프로젝트가 대학 강의 자료로 활용될 가능성
자녀 교육 시사점
- 시스템 프로그래밍의 중요성: 고수준 API 사용 능력도 중요하지만, 밑바닥에서 무슨 일이 일어나는지 이해하는 능력이 더 큰 경쟁력
- 수학적 기초: 행렬 곱, 벡터 내적, softmax, 정규화 등 수학 개념이 실제 GPU 코드에서 어떻게 구현되는지 연결
내 환경 연결
현재 RTX 3090에 llama-server(Qwen3.6-27B-MTP)를 실행 중입니다. tiny-vllm이 다루는 기술(KV 캐시, PagedAttention, 연속 배칭)이 바로 llama-server 내부에서도 사용되는 기술들입니다. tiny-vllm의 코스를 따라가면 현재 실행 중인 LLM 서버의 내부 동작을 더 깊이 이해할 수 있습니다.
관련 링크
키워드
#LLM추론 #CUDA #vLLM #PagedAttention #KV캐시 #GQA #시스템프로그래밍 #교육자료