[LLM] vLLM (Virtual Large Language Model)
최근 LLM 모델이 매우 커짐에 따라, serving 비용 또한 매우 증가하고 있다.
vLLM은 이러한 거대 LLM을 실제 환경에서 serving하기 위해 사용하는 전용 프레임워크다.
vLLM 사용하기
기본적으로 로컬 환경에서 vLLM 서버를 실행하는 명령어는 다음과 같다.
현재 작업 중인 환경 (내 PC 또는 서버)에 파이썬, vLLM, CUDA 등이 모두 설치되어 있어야 작동한다.
1
vllm serve <LLM 모델명> <옵션>
LLM 모델명에는 Hugging Face의 모델 ID를 입력한다.
즉, 허깅페이스에 등록된 레포지토리 이름을 그대로 입력하면 된다. (예: Qwen/Qwen3.5-27B)
위 명령어를 실행하면 vLLM은 가장 먼저 해당 모델이 내 컴퓨터의 HDD나 SSD에 있는지 확인하고, 없다면 허깅페이스 저장소에서 모델 파일을 자동으로 다운로드한다.
별다른 설정이 없다면, 모델은 허깅페이스 기본 캐시 폴더 ~/.cache/huggingface/hub 경로에 저장된다.
자주 사용하는 옵션은 다음과 같다.
| 옵션 | 설명 |
|---|---|
--host | 만들어진 vLLM API 서버에 누가 접속할 수 있는지를 결정 |
--port | vLLM 서버 포트 번호 설정 (vLLM의 기본값은 8000) |
--gpu-memory-utilization | vLLM 전체 시스템의 GPU 메모리 사용 비율 설정 |
-tp | 멀티 GPU 분산 처리 |
--max-model-len | 사용자의 질문과 LLM이 생성할 답변을 합친 전체 context의 최대 길이를 제한 |
--max-num-seqs | 한 번에 처리할 수 있는 최대 문장의 개수를 제한 |
--enforce-eager | CUDA Graph 비활성화 |
- vLLM 서버를 실행한 컴퓨터 (같은 IP)안에서만 접속할 수 있게 하려면
--host 127.0.0.1, 모든 외부 컴퓨터 (다른 IP)에서도 접속할 수 있게 하려면--host 0.0.0.0으로 설정한다. - 이미 컴퓨터 내에서 다른 프로그램이 8000번 포트를 사용하고 있다면,
--port옵션에서 다른 포트 번호를 설정하면 충돌을 피할 수 있다. vLLM 서버를 실행하면, 시스템은 먼저 모델 가중치를 VRAM에 올린 뒤 설정된 GPU 메모리 사용 비율 내에서 남은 공간을 전부 KV Cache로 할당한다.
하나의 GPU에서 vLLM 서버도 띄우고 다른 딥러닝 모델 학습도 동시에 돌려야 할 때, OOM 방지를 위해서
--gpu-memory-utilization=0.4처럼 낮게 설정한다.만약 오직 vLLM만 돌리는 서버라면, 최대한 많은 KV Cache 공간을 확보하기 위해
--gpu-memory-utilization=0.95처럼 높게 설정한다.- 일반적으로
--max-model-len 4096으로만 설정해도 A4 용지 2~3장 분량의 텍스트는 거뜬히 처리할 수 있다고 한다. - 만약
--max-num-seqs 2로 설정되어있으면, VRAM 공간이 넉넉하게 남아도 앞의 2개의 요청에 대해 처리를 끝낼 때까지 무조건 대기해야 한다. --enforce-eager를 사용하면, vLLM은 CUDA Graph를 끄고 파이토치의 기본 실행 방식인 Eager Mode로 돌아간다.속도를 조금 양보하는 대신, VRAM을 조금 더 확보할 수 있다.
vLLM 옵션을 아래처럼 식당에 비유하면 이해하기 더 편하다.
- VRAM: 식당 건물 전체 크기
--gpu-memory-utilization: 식당 내부에서 손님을 받을 수 있는 홀의 실제 면적--max-model-len: 손님 한 명당 차지하는 테이블의 크기--max-num-seqs: 식당에 들여놓을 수 있는 최대 테이블의 개수
vLLM 메모리 최적화
LLM 모델마다 처리할 수 있는 최대 context 길이는 정해져 있다.
vLLM은 이 context를 처리할 때 연산 속도를 높이기 위해, 서버 실행 직후 설정된 GPU 메모리 비율 내에서 남은 VRAM 전체를 KV Cache 공간으로 미리 확보한다.
만약 VRAM 용량이 적은 환경에서 --max-model-len을 모델의 최대치로 너무 높게 잡으면, 모델 가중치를 올리고 난 뒤 KV Cache를 할당할 최소한의 공간조차 부족해져 서버 초기화 단계에서 OOM 에러가 발생하며 서버가 강제 종료된다.
결국 --gpu-memory-utilization과 --max-model-len은 한정된 VRAM을 나누어 쓰는 관계다.
서버가 뻗지 않고 안정적으로 돌아가게 하려면, --gpu-memory-utilization을 높여 가용 공간을 최대한 확보하거나, 반대로 --max-model-len을 제한하여 메모리 압박을 줄여야 한다.
앞선 두 옵션의 조율을 통해 KV Cache 공간을 충분히 확보했더라도, 한 번에 처리할 수 있는 요청의 수가 낮게 제한되어 있다면 병렬 처리 효율이 떨어지게 된다.
따라서 확보된 메모리가 낭비되지 않도록 --max-num-seqs 옵션을 넉넉하게 설정해서 throughput을 극대화해야 한다.
도커 컨테이너에서 실행
Docker Hub에서 vLLM 이미지를 다운받을 수 있다.
다운받은 vLLM 이미지를 이용해 도커 컨테이너를 실행하려면 아래 명령어를 입력하면 된다.
vllm serve같은 명령어가 없는 이유는 이미지 제작자가 이 이미지의 시작 명령어를 이미 내부적으로 vllm serve로 고정해 두었기 때문이다.
우리는 <프로그램 전달 옵션>으로 vllm serve 명령어의 옵션만 따로 전달해주면 된다.
1
docker run <도커 설정 옵션> <이미지 이름> <프로그램 전달 옵션>
도커 컨테이너에서 vLLM을 실행할 때 주로 사용하는 도커 설정 옵션은 다음과 같다.
| 옵션 | 설명 | 사용 예시 |
|---|---|---|
-v <내 컴퓨터 경로>:<컨테이너 내부 경로> | 내 컴퓨터의 특정 폴더와 컨테이너 안의 폴더를 연결 (마운트) | -v ~/.cache/huggingface:/root/.cache/huggingface |
-e <변수명>=<값> | 컨테이너 내부 프로그램이 실행될 때 필요한 설정값 전달 | -e HF_TOKEN="$HF_TOKEN" |
-p <내 컴퓨터 포트>:<컨테이너 내부 포트> | 내 컴퓨터의 포트와 컨테이너 내부의 포트를 연결 | -p 8000:8000 |
-v로 내 컴퓨터에 다운로드된 모델 캐시를 컨테이너와 공유하여, 매번 모델을 다시 다운로드하는 것을 방지할 수 있다.- 허깅페이스에서 비공개 모델을 다운로드하려면 본인 확인을 위한 Access Token이 필요한데,
-e로 내 토큰값을 전달하면 권한이 필요한 모델을 정상적으로 가져올 수 있다. 도커 컨테이너는 사방이 막힌 방이라고 생각하면 된다.
따라서 vLLM 서버가 컨테이너 안에서 8000번 포트를 열고 기다려도, 밖에서 이 포트로 연결해 주지 않으면 아무도 접속할 수 없다.이때
-p를 사용하면, 컨테이너 밖에서 내 컴퓨터의 8000번 포트로 질문을 던지면, 도커가 이를 컨테이너 내부의 vLLM 서버로 전달해 줄 수 있다.