vLLM

김동준·2025년 10월 20일

vLLM의 정의

vLLM = Virtual Large Language Model (가상 대형 언어 모델)

UC Berkeley에서 개발된 오픈소스 라이브러리로, 빠르고 메모리 효율적인 LLM 추론(inference)과 서빙(serving)을 위해 설계되었습니다.

"Virtual"의 의미

"Virtual"은 운영체제의 가상 메모리(Virtual Memory)와 페이징(Paging) 기법에서 착안한 것입니다. vLLM의 핵심 기술인 PagedAttention이 바로 이 가상 메모리 개념을 KV 캐시 관리에 적용했기 때문입니다.

핵심 기술: PagedAttention

PagedAttention은 운영체제의 가상 메모리와 페이징이라는 고전적인 아이디어에서 영감을 받은 어텐션 알고리즘입니다. 전통적인 어텐션 알고리즘과 달리, PagedAttention은 연속적인 키와 밸류를 비연속적인 메모리 공간에 저장할 수 있게 합니다.

실제 예시

예시 1: 운영체제 가상 메모리와의 유사성

운영체제 Virtual Memory:
─────────────────────────
물리 메모리: [1][2][3][4][5][6][7][8]
                ↑  ↑     ↑  ↑
가상 주소:   [A][B]   [C][D]
프로세스 A는 연속적으로 보이지만 
실제로는 물리 메모리에 흩어져 있음

vLLM의 Virtual LLM:
─────────────────────────
GPU 물리 메모리: [블록1][블록2][블록3][블록4]...
                    ↑      ↑         ↑
논리 KV 캐시:    [시퀀스 A              ]
시퀀스는 연속적으로 보이지만
실제로는 물리 블록에 흩어져 있음

예시 2: 메모리 관리 비교

기존 시스템 (연속 메모리 할당):

요청 A: "긴 문서를 요약해줘" 
→ 최대 2048 토큰 분량 예약 [████████████████████████]
→ 실제 사용: 500 토큰만 사용 [█████░░░░░░░░░░░░░░░░░░░]
→ 낭비: 1548 토큰 분량 (75% 낭비!)

요청 B: "간단한 질문"
→ 최대 2048 토큰 분량 예약 [████████████████████████]
→ 실제 사용: 100 토큰만 사용 [██░░░░░░░░░░░░░░░░░░░░░░]
→ 낭비: 1948 토큰 분량 (95% 낭비!)

메모리 낭비율: 60-80%

vLLM (Virtual Memory 방식):

요청 A: "긴 문서를 요약해줘"
→ 페이지 단위로 동적 할당
→ 필요: 500 토큰 → 할당: 512 토큰 (32개 블록 × 16토큰)
→ 낭비: 12 토큰만 (2.4% 낭비)

요청 B: "간단한 질문"
→ 필요: 100 토큰 → 할당: 112 토큰 (7개 블록 × 16토큰)
→ 낭비: 12 토큰만 (12% 낭비)

메모리 낭비율: 4% 미만!

예시 3: 블록 테이블 매핑

# 개념적 예시
class VirtualLLM:
    def __init__(self):
        # 물리 메모리 블록 풀
        self.physical_blocks = [Block(i) for i in range(100)]
        
        # 블록 테이블 (OS의 페이지 테이블과 유사)
        self.block_table = {}
    
    def allocate_sequence(self, seq_id):
        """가상 메모리처럼 시퀀스 할당"""
        # 논리적으로는 연속
        logical_blocks = [0, 1, 2, 3]
        
        # 물리적으로는 비연속적으로 할당
        physical_mapping = {
            0: 5,   # 논리 블록 0 → 물리 블록 5
            1: 12,  # 논리 블록 1 → 물리 블록 12
            2: 3,   # 논리 블록 2 → 물리 블록 3
            3: 18   # 논리 블록 3 → 물리 블록 18
        }
        
        self.block_table[seq_id] = physical_mapping
        
        print("사용자 관점 (Virtual): 연속된 메모리 [0][1][2][3]")
        print("실제 GPU 메모리: 흩어진 블록 [5][12][3][18]")

# 실행
vllm = VirtualLLM()
vllm.allocate_sequence("request_1")

출력:

사용자 관점 (Virtual): 연속된 메모리 [0][1][2][3]
실제 GPU 메모리: 흩어진 블록 [5][12][3][18]

예시 4: 실제 사용 시나리오

from vllm import LLM

# Virtual LLM 초기화
# "Virtual"은 KV 캐시를 가상 메모리처럼 관리한다는 의미
llm = LLM(
    model="meta-llama/Llama-2-7b-hf",
    # 가상 메모리처럼 블록 기반 관리
    block_size=16,  # 각 블록(페이지) 크기
    # GPU 메모리의 90%를 페이지 풀로 사용
    gpu_memory_utilization=0.9
)

# 여러 요청 처리
prompts = [
    "짧은 질문",           # 2개 블록만 필요
    "중간 길이 프롬프트" * 50,  # 30개 블록 필요
    "매우 긴 문서..." * 1000    # 200개 블록 필요
]

# vLLM이 자동으로:
# 1. 각 요청에 필요한 만큼만 블록 할당 (Virtual Memory처럼)
# 2. 블록들은 GPU 메모리에 흩어져 있어도 됨
# 3. 완료된 요청의 블록은 즉시 재사용
outputs = llm.generate(prompts)

예시 5: 메모리 공유 (Copy-on-Write)

OS Virtual Memory의 Copy-on-Write를 차용:

시나리오: Beam Search로 3개의 후보 생성

원본 프롬프트 KV 캐시:
물리 블록: [1][2][3][4]

생성 경로 1:
논리: [prefix][생성1]
물리: [1][2][3][4] → [10]  ← prefix 공유!

생성 경로 2:
논리: [prefix][생성2]
물리: [1][2][3][4] → [11]  ← prefix 공유!

생성 경로 3:
논리: [prefix][생성3]
물리: [1][2][3][4] → [12]  ← prefix 공유!

결과: prefix는 메모리에 한 번만 저장되고
      3개 경로가 "가상적으로" 각자 가진 것처럼 동작

성능 개선

vLLM은 PagedAttention을 통해 HuggingFace Transformers 대비 최대 24배 높은 처리량을 제공하며, 메모리 낭비는 4% 미만으로 줄였습니다.

이는 FasterTransformer나 Orca 같은 최신 시스템보다 2-4배 높은 처리량을 달성하며, 특히 긴 시퀀스, 큰 모델, 복잡한 디코딩 알고리즘에서 더욱 두드러집니다.

정리: vLLM = Virtual Large Language Model

  • "Virtual"은 운영체제의 Virtual Memory에서 유래
  • PagedAttention으로 KV 캐시를 가상 메모리처럼 관리
  • 메모리 효율 극대화 (낭비 4% 미만)
  • 처리량 2-24배 향상
profile
Story Engineer

0개의 댓글