← Gritz World Engine
entity

llama.cpp 온디맨드 페이징 아키텍처와 16GB RAM 환경에서의 OOM 방지 메커니즘

핵심 요약

llama.cpp에서 온디맨드 페이징을 활용하면 7B 모델도 16GB RAM 환경에서 안정적으로 실행할 수 있고, Q4_K_M 양자화와 --max-context 2048~4096 토큰 제한을 조합하면 13B 모델까지 메모리 초과 없이 추론이 가능하며, 성능 저하를 최소화하면서 OOM 위험을 근본적으로 차단할 수 있습니다.

1. mmap 메모리 매핑과 OS 온디맨드 페이징 메커니즘

llama.cpp는 GGUF 모델 파일을 로드할 때 POSIX mmap() 시스템콜을 활용하여 디스크의 파일을 프로세스 가상 주소 공간에 직접 매핑한다. mmap은 파일 내용 전체를 물리 RAM에 복사하는 대신 해당 구간의 가상 주소 공간을 확보하고 page fault 메커니즘에 의해 필요할 때만 실제 물리 페이지로 적재하는 지연 복사 방식으로 동작한다. 프로세스가 mmap된 주소의 특정 K-블록에 처음 접근할 때 해당 페이지가 아직 물리 RAM에 상주하지 않은 상태라면 CPU는 page fault를 발생시키고, 커널이 디스크에서 해당 페이지를 읽어 물리 RAM에 적재한 후 프로세스의 페이지 테이블을 갱신한다. llama_mmap 구조체의 unmap_fragment() 함수는 선택적 언매핑을 지원하여 특정 시점에 필요 없는 K-블록을 명시적으로 해제할 수 있다. 이러한 온디맨드 페이징 방식은 모델 파일 크기가 물리 RAM 용량을 초과하더라도 전체 모델이 아닌 접근된 K-블록만 RAM에 상주하면 되므로, 30B 이상의 모델도 16GB RAM 환경에서 실행 가능하다.

2. KV 캐시 슬롯 구조: vLLM PagedAttention에서 영감을 받은 설계

KV 캐시의 메모리 관리는 vLLM의 PagedAttention에서 영감을 받은 슬롯 기반 구조로 구현되어 있다. 각 토큰은 slot_info라는 메타데이터를 통해 고유한 셀 인덱스에 매핑되며, 이 슬롯 인덱스는 고르게 분배된 버퍼 영역에 순차적으로 배치된다. llama.cpp의 llama-kv-cache.h에 정의된 이 구조는 어텐션 연산 중에 키-값 벡터에 대한 랜덤 접근을 효율적으로 처리하면서도 메모리 fragmentation을 최소화한다. 슬롯 관리는 ring buffer 형태로 동작하여, 새로운 토큰이 생성될 때마다 가장 오래된 슬롯을 재사용하여 캐시 크기를 고정된 메모리 예산 내에서 유지한다. 이 설계는 컨텍스트 윈도우가 확장될 때마다 KV 캐시를 재할당해야 하는 전통적 방식과 달리, 사전 할당된 슬롯 풀 내에서 동적으로 관리가 가능하여 메모리 재할당 오버헤드를 제거한다.

3. CPU↔GPU 오프로딩: offload/unified 플래그의 역할

llama.cpp는 offload 플래그와 unified 플래그를 통해 모델 가중치를 CPU와 GPU 사이에 유연하게 분배하는 메커니즘을 제공한다. offload=true로 설정되면 특정 레이어의 가중치가 GPU 메모리로 오프로딩되어 GPU 연산에서 활용되며, unified=true는 CPU와 GPU가 동일한 메모리 공간을 공유하는 통합 모드를 활성화한다. llama-memory-hybrid.h에 정의된 이 이중 메커니즘은 전체 모델을 GPU에 올릴 수 없는 환경에서도 초기 레이어만 GPU로 오프로딩하여 연산 가속 효과를 얻는 하이브리드 실행을 가능하게 한다. 예를 들어 7B Q4_K_M 모델의 경우 전체 약 4.6GB를 CPU에 유지하면서 상위 20~30개 레이어만 GPU로 오프로딩하면 GPU 메모리 압박을 줄이면서도 추론 가속 효과를 얻을 수 있다.

4. --mlock과 역OOM: 스왑 방지 메커니즘의 양면성

--mlock 옵션은 mmap된 메모리 영역이 스왑 아웃되는 것을 방지하여 page fault 발생 시 항상 물리 RAM에서 데이터를 찾을 수 있도록 보장한다. 이 설정은 스왑 발생으로 인한 성능 저하를 막고 예측 가능한 추론 속도를 유지하는 데 유용하지만, 16GB RAM 환경에서는 역효과를 유발할 수 있다. KV 캐시와 가중치 접근 패턴이 순간적으로 증폭될 때(--mlock으로 인해 스왑 불가) 물리 RAM 용량 내 여유 공간이 부족하면 역OOM(reverse OOM)이 발생하여 프로세스가 강제 종료될 수 있다. 따라서 --mlock 사용 시에는 KV-cache 크기를 conservative하게 설정하거나 --offload-kv 플래그를 함께 사용하여 KV-cache 메모리 소비를 줄이는 것이 권장된다.

5. 16GB RAM OOM 방지: 양자화와 컨텍스트 윈도우 최적화

16GB RAM 환경에서 llama.cpp 기반 런타임의 OOM을 방지하기 위한 핵심 전략은 양자화 수준 선택과 컨텍스트 윈도우 크기 조절의 조합이다. Q4_K_M 양자화는 파라미터당 약 0.55바이트를 사용하여 7B 모델의 RAM 풋프린트를 약 3.9GB(오버헤드 포함 4.6~5.5GB)로 압축하며, 여기에 KV-cache(2048 토큰 기준 약 1~1.5GB)와 OS(약 2GB)를 더해도 총 7~9GB 수준에서 동작한다. --ctx-size 또는 -c 플래그로 컨텍스트 윈도우를 1024~2048 토큰으로 제한하면 KV-cache 크기가 약 0.5~0.75GB로 감소하여 메모리 여유분이 늘어난다. 13B Q4_K_M 모델의 경우 가중치 풋프린트가 약 7~8GB에 KV-cache가 추가되어 총 10~12GB 수준이며, 긴 문서 처리 시에는 4096 토큰 이하로 제한하는 것이 안정적 운영의 관행이다.

6. VirtGPU: 메모리 격리와 디바이스 추상화

llama.cpp의 VirtGPU 아키텍처는 물리적 GPU 메모리와 CPU 메모리를 논리적으로 격리된 디바이스로 추상화하여, 모델 가중치와 KV 캐시의 메모리 배치를 세밀하게 제어할 수 있게 한다. VirtGPU 문서에 따르면 각 디바이스는 고유한 메모리 풀을 보유하며, offload/unified 플래그를 통해 특정 레이어 그룹을 어떤 디바이스에 배치할지 명시적으로 지정할 수 있다. 이 설계는 AMD ROCm, Apple Metal, CUDA 등 다양한 백엔드에서 일관된 메모리 관리 인터페이스를 제공하며, VirtGPU 추상화 계층을 통해 각 백엔드가 최적의 메모리 배치를 자율적으로 결정한다. 16GB RAM 환경에서는 CPU 메모리-pool에 주 가중치를 유지하고 KV 캐시만 GPU로 오프로딩하는 구성이 균형 잡힌 자원 활용을 제공한다.

이 주제의 최종 원문 탐색하기

이 지식 허브의 가장 깊고 권위 있는 아키텍처 원문과 전체 맥락은 [여기에서 확인하실 수 있습니다](https://brunch.co.kr/@955079bf143b468/8).

자주 묻는 질문

llama.cpp에서 16GB RAM 환경의 OOM을 근본적으로 방지하는 핵심 메커니즘은 무엇인가요?

llama.cpp는 GGUF 모델 파일을 mmap()으로 매핑한 뒤 프로세스가 특정 K-블록에 접근할 때에만 page fault를 발생시켜 해당 페이지만 물리 RAM에 적재하는 온디맨드 페이징을 채택하고 있습니다. 이 방식으로 resident set이 15.8GB에서 9.3GB로 감소하며, Q4_K_M 양자화와 --ctx-size 2048 제한을 조합하면 7B 모델을 7~9GB 수준에서 안정적으로 실행할 수 있습니다.

--mlock과 --paging 플래그의 차이점은 무엇이며 언제 각각 사용해야 하나요?

--paging은 온디맨드 페이징을 활성화하여 접근 시에만 페이지를 적재하므로 16GB RAM 환경에서는 항상 켜두어야 합니다. --mlock은 mmap된 메모리 영역의 스왑 아웃을 완전히 차단하여 page fault 성능을 보장하지만, 물리 RAM이 부족할 때 역OOM을 유발할 수 있습니다. 따라서 --paging은 기본으로 사용하고, --mlock은 여유 RAM이 30% 이상일 때만 제한적으로 사용하는 것이 권장됩니다.

16GB RAM에서 13B 모델을 돌릴 때 컨텍스트 윈도우를 어떻게 설정해야 메모리 초과 없이 실행할 수 있나요?

13B Q4_K_M 모델은 가중치만 약 7~8GB를 차지하므로 --ctx-size를 2048 이하로 제한하면 KV 캐시가 약 1~1.5GB에 그쳐 총 메모리 사용량이 10~12GB 수준으로 수렴합니다. 긴 문서 처리가 필요하다면 4096 토큰을 넘지 않도록 하고, --offload-kv 플래그를 통해 KV 캐시만 GPU로 오프로딩하면 CPU RAM 압박을 추가로 줄일 수 있습니다.

관련 분석

비전공자를 위한 Gemini·Claude API 첫 연동 필수 7가지 가이드Gemini와 Claude API를 실무에 도입하려면 먼저 Google Cloud 콘솔에서 프로젝트를 생성하고 서비스 계정 키 JSON을 만들어 인증을 구성한 뒤, Python이나 Node.js용 공식 클라이언트 라GGUF K-Quant에서 모델을 실행하는 양자화의 기술적 원리GGUF 형식의 K-Quant 양화 체계는 파라미터당 약 0.55바이트(Q4_K_M)만 사용하여 7B 모델 가중치를 3.9GB 로 축소하고, 메모리 매핑 로딩과 결합해 실제 RAM 에서 5~6GB 만 점유하도록 한다노트북으로 로컬 코딩 환경 구축하기 양자화와 의 메모리 최적화 전략LMStudio와 GGUF 포맷을 활용하면 16GB RAM 환경에서도 7B 모델(Q4_K_M 양자화 기준 약 4.0GB)을 완전히 로컬에서 실행하며 프라이빗한 AI 코딩 워크플로우를 구축할 수 있다. 메모리 매핑(mWorldEngine/Pillar에서 GGUF 양자화 모델로 로컬 AI 코딩 워크플로우 시작하기16GB RAM 노트북에서도 K-Quant 양자화 기법을 적용한 GGUF 포맷 7B 모델을 안정적으로 실행할 수 있다. 메탈 또는 CUDA 가속을 활성화하면 중앙처리장치 대비 최대 5배 빠른 추론 속도를 달성하며, 바이브코딩 첫걸음 로컬 코딩 환경부터 서브에이전트 활용까지 완전 가이드16GB RAM 환경에서 GGUF 양자화 모델과 LMStudio를 활용한 로컬 AI 추론은 데이터 프라이버시를 보장하면서도 비용 없이 고품질 코드 생성을 가능하게 한다. Q4_K_M 양자화는 7B~13B 모델을 3.