1. CUDA 1,500줄로 만든 추론 엔진, 전체 지도
jmaczan/tiny-vllm 은 Llama 3.2 1B Instruct 를 GPU 에서 돌리는 추론 엔진을 C++ 와 CUDA 로 처음부터 짠 저장소다. PyTorch 도, Hugging Face 도, 심지어 토크나이저도 쓰지 않는다. …
jmaczan/tiny-vllm 은 CUDA 로 직접 쓴 1,500 줄짜리 추론 엔진입니다. 커밋 하나에 고정해 놓고 일곱 편에 걸쳐 읽습니다.
가중치를 올리고 GPU 버퍼를 잡는 일부터 시작해, 프롬프트 전체를 한 번에 흘리는 prefill 경로, cuBLAS 에 행렬을 뒤집어 넘기는 이유, 토큰 하나를 만드는 decode 경로와 전용 커널, KV 캐시를 16토큰 블록으로 쪼개 block table 로 읽는 방법, 슬롯과 큐로 여러 요청을 겹치는 continuous batching 까지 따라갑니다.
jmaczan/tiny-vllm 은 Llama 3.2 1B Instruct 를 GPU 에서 돌리는 추론 엔진을 C++ 와 CUDA 로 처음부터 짠 저장소다. PyTorch 도, Hugging Face 도, 심지어 토크나이저도 쓰지 않는다. …
이 엔진에서 main() 은 cuBLAS 핸들을 만든 뒤 곧바로 두 가지를 한다(src/main.cpp:557-569 ). model.safetensors 파일에서 가중치를 꺼내 GPU 메모리에 올리는 일, 그리고 앞으로 모든 계산이 쓸 버퍼를 미리 …
1편에서 prefill() 은 프롬프트 전체를 한 번에 처리하는 함수라고 했다. 17개 토큰이 한 호출 안에서 임베딩부터 다음 토큰 선택까지 통과한다. 이번 편은 그 함수의 안을 본다. 토큰들이 레이어 하나를 지나는 동안 어떤 커널을, 어떤 순서로 거 …
3편에서 Q/K/V 투영을 볼 때 이런 문장을 적어 두고 넘어갔다. “활성과 가중치는 행 우선인데 cuBLAS 는 열 우선을 가정하므로, CUBLAS_OP_T 전치 플래그와 lda/ldb/ldc 만으로 호출한다. 왜 이렇게 부르는지는 4편이 …
prefill 이 프롬프트 전체를 한 번에 흘려 보내면, 그다음부터는 지금까지 만든 토큰을 바탕으로 토큰을 하나씩 만들어야 한다. 이 단계가 decode 다. 1편에서 본 대로 prefill 과 decode 는 연산의 모양이 달라서 — 전자는 행렬 × …
decode 가 토큰을 하나 만들 때마다 어텐션은 그 시퀀스가 지금까지 쌓은 모든 K/V 를 다시 읽는다. 이 K/V 를 시퀀스마다 연속된 큰 버퍼 하나로 잡으면, 시퀀스들이 저마다 다른 시점에 끝나면서 안 쓰는 구간이 생겨 메모리가 낭비된다. …
GPU 는 한 번에 한 시퀀스만 처리하면 그 시퀀스가 prefill 을 마치고 decode 로 넘어가는 사이에서 쉬게 된다. continuous batching 은 처리 중이던 요청이 끝나는 대로 그 자리에 큐에서 기다리던 다음 요청을 넣어 GPU 를 …