Skip to content

필사 모드: vLLM 내부 구조 (7) — 배포 튜닝과 흔한 함정, OOM 진단 순서

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

튜닝 순서를 먼저 정하기

여섯 편에 걸쳐 내부를 봤으니 마지막은 배포입니다. 다만 손잡이를 나열하기 전에 순서부터 정하고 시작하겠습니다. 튜닝이 실패하는 가장 흔한 이유는 잘못된 값을 골라서가 아니라 여러 값을 한꺼번에 바꿔서 무엇이 효과가 있었는지 모르게 되기 때문입니다.

권하는 순서는 이렇습니다. 첫째, 모델이 GPU에 들어가게 만듭니다. 둘째, 길이 한도를 워크로드에 맞춥니다. 셋째, KV 캐시 여유를 확보합니다. 넷째, 그 뒤에야 배치와 지연을 조절합니다. 앞의 세 단계가 안 잡힌 상태에서 배치 인자를 만지면 대개 아무 일도 일어나지 않습니다.

내용은 2026-08-12에 공식 문서·소스에서 확인했습니다. vLLM은 변화가 빠르니 설정값과 동작은 사용 중인 버전의 문서로 다시 확인하세요.

# 이 글에서 다루는 인자들이 모이는 전형적인 형태
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.92 \
  --tensor-parallel-size 1 \
  --max-num-seqs 128

gpu_memory_utilization — 가장 먼저 만지는 값

공식 문서의 정의는 이렇습니다. 모델 실행기가 쓸 GPU 메모리의 비율이고, 0과 1 사이의 값을 가집니다. 그리고 제가 2026-08-12에 문서와 main 브랜치 CacheConfig 소스에서 확인한 선언 기본값은 0.92였습니다. 오래된 글에는 다른 숫자가 적혀 있을 수 있으니 사용 중인 버전에서 직접 확인하세요.

이 값이 중요한 이유는 1편과 6편에서 본 구조 때문입니다. vLLM은 이 비율만큼의 메모리를 확보한 뒤, 거기서 가중치와 오버헤드를 뺀 나머지를 전부 KV 캐시로 씁니다. 즉 이 값을 올리면 곧바로 KV 캐시가 커지고, 더 긴 요청과 더 많은 동시 요청을 감당하게 됩니다.

그렇다고 1에 가깝게 올리면 되느냐 하면 그렇지 않습니다. 이 비율은 GPU 전체를 기준으로 계산되므로 같은 GPU를 쓰는 다른 프로세스가 있으면 계산이 어긋납니다. 쿠버네티스에서 GPU를 공유하는 구성이라면 특히 그렇습니다. 또 단편화나 일시적인 활성화 텐서 때문에 실사용은 계산보다 조금 더 나오므로, 여유를 0으로 만들면 평소에는 멀쩡하다가 특정 요청 조합에서만 터집니다.

값을 올려도 처리량이 안 늘어난다면 한도가 메모리가 아닌 다른 곳에 있다는 신호입니다. max_num_seqsmax_num_batched_tokens가 먼저 걸리고 있을 수 있습니다.

텐서 병렬과 파이프라인 병렬

여기서 가장 흔한 오해를 먼저 걷어내겠습니다. 텐서 병렬은 성능 옵션이 아니라 용량 옵션입니다.

공식 문서의 기준은 명확합니다. 모델이 GPU 한 장에는 안 들어가지만 한 노드의 여러 GPU에는 들어갈 때 텐서 병렬을 씁니다. 한 노드에도 안 들어갈 때 파이프라인 병렬을 함께 씁니다. 설정 방법도 문서가 직접 제시합니다. tensor_parallel_size를 노드당 GPU 수로, pipeline_parallel_size를 노드 수로 두는 것입니다. 문서가 든 예로 노드 2대에 GPU 8장씩이면 텐서 병렬 8, 파이프라인 병렬 2가 됩니다.

문서가 언급한 예외 상황도 알아 둘 만합니다. 한 노드 안에서 GPU 수가 균등하게 나눠지지 않는 경우에는 텐서 병렬을 1로 두고 파이프라인 병렬을 GPU 수로 두어 층을 불균등하게 쪼갤 수 있습니다.

tensor_parallel_size의 기본값은 문서에서 1로 확인했습니다. 즉 아무것도 안 주면 GPU 한 장을 씁니다. 서버에 GPU가 여러 장 꽂혀 있어도 그렇습니다. 멀티 GPU 장비에서 성능이 기대에 못 미친다면 이 값부터 확인하세요.

한 장에 이미 들어가는 모델에 텐서 병렬을 걸면 어떻게 될까요. 각 GPU가 자기 몫의 KV 캐시를 갖게 되어 총 캐시가 늘어나는 이득은 있지만, 층마다 GPU 사이 통신이 추가됩니다. 그래서 실측 없이 무조건 이득이라고 말할 수 없습니다. 4편에서 본 것처럼 공식 문서가 선점 대응책 목록에 텐서 병렬 상향을 올려 둔 이유는 처리 속도가 아니라 캐시 공간 때문입니다.

양자화 선택

양자화는 가중치를 더 적은 비트로 표현해 메모리를 줄입니다. 그리고 줄어든 만큼이 그대로 KV 캐시로 돌아갑니다. 6편의 구조를 떠올리면 이 이득이 왜 큰지 분명합니다. 같은 GPU에서 더 긴 컨텍스트와 더 많은 동시 요청을 얻습니다.

vLLM 문서가 다루는 방식은 여러 갈래입니다. AutoAWQ, BitsAndBytes, GPTQModel, Intel Neural Compressor, LLM Compressor, NVIDIA Model Optimizer, AMD Quark, TorchAO 등이 문서에 나열되어 있고, LLM Compressor 쪽은 FP8 W8A8, INT4 W4A16, INT8 W8A8 같은 조합을 다룹니다. 문서는 시작점으로 LLM Compressor를 안내합니다.

고를 때 실제로 중요한 것은 방식 이름이 아니라 두 가지입니다.

하드웨어 지원입니다. 문서는 양자화 구현마다 하드웨어 플랫폼 호환성이 다르다는 표를 제공하면서, 이 호환성 표가 계속 바뀔 수 있다고 명시합니다. 그러니 이름만 보고 고르지 말고 여러분의 GPU 세대에서 실제로 지원되는지 표를 확인하세요. 잘못 고르면 아예 안 뜨거나, 뜨더라도 가속을 못 받아 느려집니다.

이미 양자화된 모델인지 여부입니다. --quantization 인자의 설명은 가중치 양자화 방법을 지정한다는 것이고, 값을 주지 않으면 모델 설정 파일의 양자화 설정을 확인한다고 되어 있습니다. 즉 허브에서 이미 양자화된 체크포인트를 받아 쓴다면 대개 따로 지정하지 않아도 됩니다.

품질 이야기도 빼놓을 수 없습니다. 양자화는 공짜가 아니고 정확도에 영향을 줍니다. 얼마나 영향을 주는지는 모델과 방식과 과제에 따라 다릅니다. 그러니 여기서 "4비트는 괜찮다" 같은 일반화를 하지 않겠습니다. 여러분의 평가셋으로 직접 재는 것 말고 답이 없습니다.

KV 캐시 자료형

가중치만 줄일 수 있는 것이 아닙니다. KV 캐시 자체의 자료형도 설정 항목입니다. --kv-cache-dtype의 문서 설명은 KV 캐시 저장에 쓸 자료형이고, auto이면 모델의 자료형을 따른다는 것입니다. 기본값은 문서와 소스 모두에서 auto로 확인했습니다. 소스에는 CUDA 11.8 이상에서 fp8 계열을 지원한다는 설명이 함께 붙어 있습니다.

이 손잡이가 매력적인 이유는 효과가 정확히 KV 캐시에만 꽂히기 때문입니다. 가중치는 그대로 두고 캐시만 절반으로 줄이면, 같은 메모리로 길이나 동시성을 늘릴 수 있습니다. 다만 이것도 정밀도 손실이므로 평가 없이 켜지는 마세요.

OOM 진단 순서

메모리 부족은 vLLM 운영에서 가장 자주 만나는 문제입니다. 진단의 첫 단추는 언제나 하나입니다. 기동 중에 났는지 운영 중에 났는지를 먼저 가릅니다.

기동 중에 실패했다면 원인은 둘 중 하나입니다.

가중치가 안 들어간 경우입니다. 모델을 적재하는 단계에서 죽습니다. 해법은 양자화, 텐서 병렬, 더 작은 모델입니다. gpu_memory_utilization을 올리는 것은 큰 도움이 안 됩니다. 이미 대부분을 주고 있는데도 가중치가 안 들어가는 상황이기 때문입니다.

KV 캐시가 부족한 경우입니다. 6편에서 본 그 에러입니다. 최대 시퀀스 길이가 KV 캐시에 담을 수 있는 토큰 수보다 크다는 메시지가 나오고, 에러 자체가 해법을 알려 줍니다. gpu_memory_utilization을 올리거나 max_model_len을 줄이는 것입니다. 실무에서는 후자가 먼저입니다. 대개 실제 워크로드에 필요한 것보다 길게 열어 둔 상태이기 때문입니다.

운영 중에 났다면 이야기가 다릅니다. vLLM은 기동 시점에 캐시를 미리 잡아 두므로, 정상적인 상황이라면 요청이 늘어난다고 갑자기 OOM이 나지는 않습니다. 요청이 많아지면 OOM 대신 4편에서 본 선점이 일어납니다. 그래서 운영 중 OOM은 대개 vLLM 바깥에 원인이 있습니다. 같은 GPU에 다른 프로세스가 들어왔거나, gpu_memory_utilization이 실제 여유보다 크게 잡혀 있었거나, 평소에 안 나오던 크기의 멀티모달 입력이 들어온 경우입니다.

그리고 자주 오진되는 경우가 하나 더 있습니다. OOM은 아닌데 갑자기 느려지는 상황입니다. 이때는 메모리 인자를 만지기 전에 선점 경고 로그부터 확인하세요. 선점이 반복되고 있다면 그것은 성능 문제가 아니라 용량 문제입니다.

흔한 함정 다섯 가지

시리즈 전체에서 반복해 나온 함정들을 모아 둡니다.

함정결과관련 편
오래된 글의 설정을 그대로 복사제거된 인자를 쓰게 됨. 특히 스왑 관련 설정은 V1에서 빠졌습니다4편
gpu_memory_utilization을 한계까지 상향평소엔 멀쩡하다 특정 요청 조합에서만 터짐이 글
max_model_len을 모델 최대치로 개방아무도 안 쓰는 길이를 감당하느라 동시 처리 능력을 잃음6편
애플리케이션에서 생성 상한을 상수로 고정긴 입력이 들어오는 순간 요청이 거부됨6편
프롬프트 맨 앞에 타임스탬프나 세션 식별자접두사 캐시가 통째로 무효화. 인자로는 해결 불가5편

마지막 줄이 특히 중요합니다. 앞의 네 개는 설정을 고쳐 해결되지만, 이건 프롬프트 설계의 문제라 어떤 인자를 만져도 나아지지 않습니다.

일곱 편을 관통하는 결론은 하나입니다. vLLM에서 성능은 대체로 KV 캐시를 얼마나 아끼고 재사용하는가의 문제입니다. 블록으로 쪼개고, 스텝마다 다시 채우고, 겹치는 앞부분을 공유하고, 길이 한도로 최악의 경우를 제한하는 것까지 전부 같은 이야기의 다른 면입니다.

직접 해보기

참고 자료

현재 단락 (1/52)

여섯 편에 걸쳐 내부를 봤으니 마지막은 배포입니다. 다만 손잡이를 나열하기 전에 순서부터 정하고 시작하겠습니다. 튜닝이 실패하는 가장 흔한 이유는 잘못된 값을 골라서가 아니라 여러...

작성 글자: 0원문 글자: 5,073작성 단락: 0/52