대규모 언어 모델(LLM)을 서비스로 제공하는 것은 엄청난 비용이 듭니다. GPT-3와 같은 거대 모델을 서빙하려면 여러 대의 고성능 GPU가 필요하며, 요청 하나를 처리하는 데 드는 비용이 기존 검색 쿼리의 10배에 달할 수도 있습니다. 이 비용을 줄이고 더 많은 사용자를 동시에 처리하기 위한 핵심은 처리량(Throughput), 즉 단위 시간당 처리할 수 있는 요청의 수를 높이는 것입니다.
처리량을 높이려면 여러 사용자의 요청을 한 번에 모아 처리하는 배치(Batching) 기술이 필수적입니다. 하지만 LLM 서빙에서 배치 크기를 무작정 늘리는 데에는 치명적인 병목이 존재합니다. 바로 GPU 메모리 부족 문제입니다. 특히, LLM의 '단기 기억' 역할을 하는 KV 캐시(Key-Value Cache)라는 동적 메모리 영역이 비효율적으로 관리되면, 귀중한 GPU 메모리가 순식간에 고갈되어 버립니다.
이 글에서는 기존 LLM 서빙 시스템의 고질적인 메모리 관리 문제를 진단하고, 모든 개발자에게 익숙한 운영체제(OS)의 가상 메모리 기법에서 영감을 얻어 이 문제를 해결한 PagedAttention과 이를 구현한 시스템 vLLM에 대해 깊이 있게 탐구합니다.
LLM은 다음 단어를 예측하기 위해 이전에 생성된 모든 단어(토큰)들을 참고합니다. 이때 어텐션 메커니즘은 각 토큰으로부터 'Key'와 'Value'라는 핵심 정보를 계산합니다. 매번 전체 문맥을 다시 계산하는 것은 매우 비효율적이므로, 한 번 계산된 Key와 Value 값은 재사용을 위해 GPU 메모리에 캐싱해 둡니다. 이것이 바로 KV 캐시이며, LLM의 '단기 기억' 역할을 담당합니다.
문제는 이 KV 캐시의 크기가 가변적이라는 것입니다. 사용자의 입력 길이나 생성되는 문장의 길이에 따라 필요한 메모리 양이 동적으로 변합니다.
기존 서빙 프레임워크들은 KV 캐시를 관리하는 데 심각한 비효율성을 보입니다. 그 근본 원인은 '연속적인 메모리 할당(Contiguous Memory Allocation)' 정책 때문입니다.
개발자 친화적 비유: '고정 좌석 영화관'
- 과잉 예약: 한 그룹(하나의 요청)이 영화관(GPU 메모리)에 들어옵니다. 시스템은 이 그룹이 얼마나 커질지 모르기 때문에, 이들이 최대로 차지할 수 있는 가장 긴 줄(최대 토큰 길이, 예: 2048석)을 통째로 예약해 버립니다.
- 내부 파편화: 하지만 실제로 이 그룹의 인원은 10명(실제 생성된 토큰 길이)에 불과할 수 있습니다. 그럼에도 불구하고 예약된 2048석 전체는 다른 그룹이 사용할 수 없게 됩니다. 이렇게 예약은 되었지만 사용되지 않는 공간이 바로 내부 파편화(Internal Fragmentation)로 인한 심각한 메모리 낭비입니다.
- 외부 파편화: 여러 그룹이 서로 다른 길이의 줄(512석, 1024석, 2048석 등)을 예약했다가 빠져나가면, 영화관에는 여기저기 자투리 좌석들이 남게 됩니다. 이 자투리들을 모두 합치면 새로운 대규모 그룹을 받을 수 있는 충분한 공간이 있지만, 좌석들이 연속적으로 이어져 있지 않아서 결국 새 그룹을 받지 못하는 상황이 발생합니다. 이것이 외부 파편화(External Fragmentation)입니다.
논문에 따르면, 이러한 내부 및 외부 파편화 때문에 실제 KV 캐시 데이터가 차지하는 메모리는 전체 할당된 공간의 20%에 불과할 수 있습니다. 다시 말해, 무려 80%의 귀중한 GPU 메모리가 아무것도 하지 않은 채 낭비되고 있는 것입니다.
이 고질적인 메모리 낭비 문제를 해결하기 위해, 논문은 PagedAttention이라는 혁신적인 알고리즘을 제안합니다. 이 아이디어는 놀랍게도 컴퓨터 과학의 근간을 이루는 운영체제(OS)의 가상 메모리(Virtual Memory)와 페이징(Paging) 기법에서 나왔습니다.
운영체제는 거대한 프로그램을 실행할 때, 프로그램의 논리적인 주소 공간을 '페이지(Page)'라는 고정된 크기의 블록으로 나눕니다. 그리고 이 페이지들을 실제 물리 메모리(RAM)의 비어있는 '프레임(Frame)'에 꼭 연속적이지 않더라도 자유롭게 할당합니다. 이때 페이지 테이블(Page Table)이 논리 페이지와 물리 프레임 간의 주소 매핑을 관리해주기 때문에, 프로그램 입장에서는 마치 거대하고 연속적인 메모리 공간을 사용하는 것처럼 착각하게 됩니다.
PagedAttention은 이 아름다운 원리를 KV 캐시 관리에 그대로 적용합니다.
• KV 캐시를 블록(Block)으로 분할: 연속적인 토큰들의 KV 캐시를 작은 '블록'이라는 고정 크기 단위로 나눕니다.
• 비연속적 메모리 할당: 이 블록들을 GPU 메모리 여기저기 흩어져 있는 비어있는 공간에 자유롭게 할당합니다.
• 블록 테이블(Block Table)로 관리: 어떤 논리적 순서의 블록이 어떤 물리적 메모리 주소에 저장되었는지 '블록 테이블'이 페이지 테이블처럼 기록하고 관리합니다.
개발자 친화적 비유: '자유 좌석 레스토랑'
- 손님 그룹(하나의 요청)이 들어옵니다. 레스토랑은 최대 인원을 예상해 거대한 테이블을 통째로 예약할 필요가 없습니다.
- 오는 손님(새로 생성되는 토큰) 수에 맞춰 작은 테이블(블록)을 하나씩 유연하게 내어주면 됩니다. 이 테이블들은 레스토랑 곳곳에 흩어져 있어도 전혀 문제없습니다.
- 웨이터(블록 테이블)가 각 그룹의 손님들이 어느 테이블에 흩어져 앉아있는지만 정확히 기억하고 서빙하면 됩니다.
"이 방식 덕분에 낭비되는 좌석이 거의 사라지고, 레스토랑(GPU 메모리)은 훨씬 더 많은 손님(요청)을 효율적으로 받을 수 있게 됩니다. 내부 파편화는 블록 내에서만 발생하여 미미해지고, 외부 파편화는 완전히 사라집니다."
PagedAttention이라는 천재적인 알고리즘을 현실로 구현한 것이 바로 vLLM 서빙 시스템입니다. vLLM은 PagedAttention을 중심으로 다음과 같이 동작합니다.
fork()
시스템 콜이 자식 프로세스를 생성할 때 메모리를 효율적으로 관리하는 방식과 매우 유사합니다.
말로만 뛰어난 것이 아닙니다. 논문은 vLLM이 당시 SOTA(State-of-the-art) 시스템이었던 HuggingFace Transformers, FasterTransformer 및 Orca와 비교하여 얼마나 뛰어난 성능을 보이는지 구체적인 수치로 증명합니다.
비교 항목 | vLLM 성능 향상 (Orca 대비) |
---|---|
처리량 (Throughput) | 2-4배 증가 (동일한 답변 지연 시간 기준) |
배치 가능한 요청 수 | 최대 4.3배 더 많은 요청을 한 배치로 처리 가능 |
메모리 효율성 | 낭비되는 메모리 거의 없음 (near-zero waste) |
특히 효과적인 시나리오 | - 긴 문장(Long sequence) 처리 시 - 거대 모델(Large models) 서빙 시 - 빔 서치 등 복잡한 디코딩 알고리즘 사용 시 |
특히, 여러 개의 답변 후보를 동시에 탐색하는 빔 서치(Beam Search)의 경우, 여러 후보 시퀀스가 초반 토큰들을 공유하므로 Copy-on-Write의 메모리 절약 효과가 극대화됩니다. 그 결과, Orca 대비 최대 2.3배의 처리량 향상을 보였습니다. 이는 vLLM의 유연한 블록 공유 메커니즘이 얼마나 강력한지를 명확히 보여주는 결과입니다.
LLM 서빙의 성능과 비용은 단순히 GPU의 연산 능력에만 달려있는 것이 아니라, 한정된 메모리 자원을 얼마나 지능적으로 관리하는가에 달려있다는 중요한 교훈을 얻을 수 있습니다.
PagedAttention과 vLLM은 LLM 서빙의 비용을 크게 절감하고, 더 많은 개발자와 기업이 LLM 기술을 활용할 수 있도록 진입 장벽을 낮추는 핵심 기술입니다. 앞으로 LLM 생태계가 더욱 폭발적으로 확장되는 데 있어 vLLM과 같은 효율적인 서빙 시스템이 중추적인 역할을 할 것으로 기대됩니다.