결과를 바꾸는 엔진 노브
엔진 기본값 대부분은 데모에는 합리적이고 실사용에는 틀렸습니다. 노브 서넛이 결과를 바꿉니다. 컨텍스트 길이, GPU 오프로드, KV 캐시 타입, 플래시 어텐션. 나머지는 가장자리의 튜닝입니다. 이 페이지는 llama.cpp 플래그 이름을 쓰고 끝에 Ollama 등가물을 둡니다 — 개념은 모든 엔진에 이전됩니다.
컨텍스트 길이: 조용한 기본값의 함정
엔진은 보수적인 기본값을 배송합니다. llama.cpp는 역사적으로 512 그다음 4096, Ollama는 버전에 따라 2048–4096(집필 시점 기준 OLLAMA_CONTEXT_LENGTH는 대략 4k에 착륙). 한편 당신의 모델은 네이티브로 32k–128k를 지원할 수 있습니다. 4k 컨텍스트에 20k 토큰 문서를 붙여넣으면 둘 중 하나가 일어나고 둘 다 나쁩니다. 하드 에러("request exceeds available context") 또는 가장 오래된 메시지의 조용한 잘림. 어느 쪽 에러 메시지도 초보자에게 자기를 설명해주지 않습니다.
계산 예제: ~12k 토큰짜리 계약서와 질문 하나를 기본 4096 창에 넣습니다. 엔진은 가장 최근 소재를 유지하고 문서의 시작을 버립니다. 그리고 모델은 파일의 잘못된 절반에 대한 질문에 자신만만하게 답합니다. 멍청한 모델처럼 보입니다. 잘린 프롬프트일 뿐입니다.
해결은 기계적입니다. 매 실행마다 컨텍스트 크기를 실제 프롬프트와 예상 출력에 맞춰 명시적으로 넘기고, 시작 로그에 n_ctx = 16384(또는 고른 값)가 찍히는지 확인하세요. 한국어 비고: 같은 토크나이저에서 한국어 텍스트는 영어보다 덜 조밀하게 토큰화되는 경우가 많습니다 — 한국어 페이지가 영어 페이지보다 많은 토큰을 쓸 수 있습니다(토큰 참고) — 그래서 컨텍스트 압력은 예상보다 일찍 도착합니다.
# 함정: 기본값은 엔진마다, 버전마다 다름
llama-server -m model.gguf # n_ctx = 4096 정도로 시작
# 해결: 명시적으로, 그리고 시작 로그에서 검증
llama-server -m model.gguf -c 16384 # 로그 출력: n_ctx = 16384
GPU 오프로드: n_gpu_layers
-ngl / --n-gpu-layers는 transformer 레이어 중 몇 개가 GPU에 사는지 정합니다. "전부"를 뜻하는 큰 숫자를 99처럼 쓰세요(지원되는 곳에서는 -1). 부분 오프로드의 증상은 특징적입니다. 괜찮은 GPU가 있는 장비에서 3–10 tok/s. 로드 로그 라인으로 확인하세요. 예: offloaded 33/33 layers to GPU. VRAM이 모델과 KV 캐시를 못 담으면 정직한 선택지는 더 작은 quant, 양자화된 KV 캐시, 또는 덜 오프로드하는 것입니다 — 단, CPU에 남는 모든 레이어가 루프 전체를 CPU 리듬으로 끌고 간다는 것을 알아두세요(속도 참고). 거의 들어가는 모델을 반쯤 오프로드하는 것은 보통 quant 한 단계 하향보다 나쁩니다.
반대 방향의 상식 확인도 하세요. -ngl 0는 순수 CPU를 강제하는데, 그것이 "GPU" 설정과 같은 속도라면 GPU는 아무것도 하고 있지 않았던 것입니다.
스레드 (CPU 모드만)
CPU 모드에서는 -t를 SMT 스레드 수가 아니라 물리 코어 수로 설정하세요. 8코어/16스레드 칩에서는 8을 씁니다. 물리 코어보다 많은 스레드는 경합을 일으켜 디코드를 늦춥니다. 프롬프트 처리에는 별도 노브(--threads-batch)가 있습니다. 같은 규칙이 적용됩니다.
메모리: mmap과 --mlock
llama.cpp는 기본적으로 모델 파일을 메모리 매핑합니다. 시작이 빠르고 안 건드린 레이어는 RAM을 쓰지 않습니다. 트레이드오프는 메모리 압박 하에서 OS가 페이지를 쫓아낼 수 있다는 것 — 세션 몇 시간 뒤에 원인 모를 멈춤으로 나타납니다. --mlock는 모델을 고정해 쫓겨나지 않게 합니다 — 바쁜 기계에서 유용하고, 기가바이트를 다른 모든 것으로부터 잠근 대가가 따릅니다. Ollama는 이것을 내부에서 처리합니다. 공유 장비에서 날것 llama.cpp를 쓰는 사람은 이 플래그의 존재를 알아야 합니다.
플래시 어텐션
-fa / --flash-attn은 어텐션 단계의 메모리 트래픽을 줄이고 최근 llama.cpp 빌드에서는 기본 켜짐(또는 자동)입니다. 긴 컨텍스트에서 가장 중요하고, 현재 빌드에서 V 캐시 양자화는 이것을 요구합니다. 새 빌드가 당신의 GPU 백엔드에서 말썽이면 이것이 첫 번째로 토글할 플래그입니다 — 그리고 최신 빌드에서는 조용히 꺼지지 않았는지가 가장 먼저 확인할 것입니다.
KV 캐시 양자화
--cache-type-k q8_0 --cache-type-v q5_0는 KV 캐시를 16비트 부동소수점 대신 8비트/5비트로 저장해, 사소한 품질 비용으로 KV 메모리를 대략 절반 이하로 깎습니다 — 같은 VRAM에서 더 긴 컨텍스트를 의미합니다. KV 캐시가 무엇인지, 정확한 크기 수학은 KV 캐시에.
전형적 이득: q8_0 K와 q5_0 V는 챗 과제에서 거의 보이지 않는 변화로 KV 크기를 대략 절반으로 만듭니다 — 믿기 전에 당신 워크로드에서 검증하세요.
프롬프트 배치 크기
-b / --batch-size는 프리필(프롬프트 처리)의 청크 크기입니다. 배치가 크면 긴 프롬프트에서 첫 토큰까지 빨라지고, 피크 VRAM을 조금 더 씁니다. 긴 붙여넣기가 시작이 느리게 느껴지면 모델 탓 전에 이것을 올리세요.
컨텍스트 늘리기: rope scaling과 YaRN
--rope-scaling yarn --rope-factor 2.0은 위치 빈도를 재스케일해 32k 네이티브 모델을 64k 쪽으로 늘립니다. 작동합니다. 품질 경사가 있습니다. 네이티브 창 근처에서는 저하가 작고 창을 넘어 늘릴수록 커집니다. 중요한 것이라면 늘리기보다 네이티브 컨텍스트가 필요를 이미 커버하는 모델을 선호하세요(모델 선택 참고).
집필 시점 기준으로 Ollama는 Modelfile에 rope scaling을 노출하지 않습니다. 늘린 컨텍스트 실험은 llama.cpp를 직접 띄우는 것을 의미합니다.
주석 달린 실행 라인
llama-server -m qwen3-8b-q4_k_m.gguf --host 127.0.0.1 --port 8080 -c 16384 -ngl 99 -fa on -b 2048 --cache-type-k q8_0 --cache-type-v q5_0
| 플래그 | 하는 일 | 주의 |
|---|---|---|
-c 16384 |
컨텍스트 창 (프롬프트 + 출력이 공유) | 기본값에 의존하지 마세요; 명시적으로 설정 |
-ngl 99 |
GPU로 오프로드할 레이어 (99 = 전부) | offloaded N/N 로그 라인 확인 |
-fa on |
플래시 어텐션 | 최근 빌드에서 기본 auto; V 캐시 양자화에 필요 |
-b 2048 |
프롬프트 처리 배치 | 피크 VRAM을 약간 올림; TTFT에 도움 |
--cache-type-k/-v |
KV 캐시 dtype | V 양자화는 플래시 어텐션 필요 |
--host 127.0.0.1 |
루프백만 바인딩 | 노출 규칙은 서빙에 |
Ollama 등가물
# 모델별, Modelfile 안에서:
PARAMETER num_ctx 16384
PARAMETER num_gpu 99
# 또는 전역으로, 서비스 시작 전에:
export OLLAMA_CONTEXT_LENGTH=16384
export OLLAMA_FLASH_ATTENTION=1
export OLLAMA_KV_CACHE_TYPE=q8_0
Ollama는 요청이 num_ctx를 초과하면 경고를 로그에 남깁니다 — 이것들을 바꾼 뒤 로그를 한 번 읽으세요. 환경 변수를 통한 변경은 서비스 재시작이 필요합니다.
Ollama가 실제로 적용한 것을 보려면: ollama show model --modelfile이 확정된 파라미터를 찍고, OLLAMA_DEBUG=1이 서비스 로그에 실제 컨텍스트와 오프로드 수를 남기게 합니다.
샘플러는 엔진 노브가 아닙니다
Temperature, top-p, 반복 페널티 — 이들은 어떤 토큰이 선택되는지를 빚지, 얼마나 빠르거나 메모리에 얼마나 들어가는지가 아닙니다. 그들은 샘플링에 삽니다. 출력이 이상한데 속도와 메모리가 괜찮다면 이 페이지가 아니라 그 페이지가 필요합니다.
규칙
컨텍스트를 명시적으로 설정하세요. 실행 설정을 바꿀 때마다 로그 라인 — n_ctx = ...과 offloaded N/N layers — 으로 검증하세요. 기본값은 첫 데모가 시작되도록 튜닝된 것이지 당신 워크로드가 서빙되도록 튜닝된 것이 아닙니다.
llm_load_tensors: offloaded 33/33 layers to GPU
n_ctx = 16384
두 라인 모두 실행 수 초 안에 찍힙니다. 한 번 grep해보면 설정은 더 이상 속설이 아닙니다.