토론 목적이라기보다는 기록(documentation)을 위해 이 글을 게시합니다. 이 조합에 대한 수치를 어디에서도 찾을 수 없었기에, 제가 정확히 무엇을 실행하고, 무엇이 들어맞으며, 어떻게 작동하는지 공유합니다. 유용하다면 설정을 복사해 사용하시고, 틀린 부분이 있다면 수정해 주세요.
하드웨어
GPU: RTX 4090, 24 GB
CPU: Intel Core i9-13900K (8 P-cores + 16 E-cores, 32 threads)
RAM: 128 GB DDR5 (4 x 32 GB Kingston Fury, 정격 5600, 5200으로 동작), 듀얼 채널
OS: Windows 11 Pro
llama.cpp 빌드: 10240 ( 0b14b87d7 ), Clang 20.1.8, Windows x86_64
128 GB의 RAM은 여유 공간이 아니라 필수 요구 사항입니다. UD-Q3_K_M은 4개의 샤드(shards)에 걸쳐 121 GB를 차지합니다. GPU는 어텐션 가중치(attention weights)와 KV 캐시(KV cache)를 보유하며, 그 외의 모든 것은 시스템 RAM에 위치합니다.
모델이 로드되어 서비스 중일 때 측정된 수치:
| 이름 | WorkingSetGB | PrivateGB |
|---|
| llama-server | 103.2 | 127.7 |
103 GB 상주(resident), 128 GB 커밋(committed) — 기계 전체를 사용합니다. 두 수치 사이의 약 24 GB 차이는 VRAM에 들어있는 양과 밀접하게 일치하는데, 이는 GPU 상주 텐서(tensors)가 업로드된 후 호스트 측 복사본이 제거되는 것으로 해석됩니다. 어느 쪽이든: 이 양자화(quant) 버전은 64 GB에서는 실행되지 않으며, 128 GB에서는 남는 공간이 전혀 없습니다.
실행 중인 모델: unsloth/DeepSeek-V4-Flash-GGUF:UD-Q3_K_M (65536 컨텍스트, KV 캐시는 q8_0로 양자화, 단일 슬롯).
24 GB VRAM 중 22483–22836 MiB가 안정적으로 사용 중입니다.
--no-mmap 사용 시 로드 시간은 약 60초입니다.
설정(config):
llama-server.exe ^
-hf unsloth/DeepSeek-V4-Flash-GGUF:UD-Q3_K_M ^
--host 127.0.0.1 ^
--port 8096 ^
-c 65536 ^
-np 1 ^
-ngl 999 ^
--n-cpu-moe 39 ^
--flash-attn auto ^
--cache-type-k q8_0 ^
--cache-type-v q8_0 ^
-ub 2048 ^
-b 4096 ^
-t 24 ^
-tb 24 ^
--jinja ^
--no-mmap ^
--metrics ^
--temp 1.0 ^
--top-k 20 ^
--top-p 0.95 ^
--min-p 0.0
아이디어는 MoE(Mixture of Experts)의 일반적인 방식과 같습니다: 어텐션(attention)과 KV 캐시는 GPU에, 전문가 FFN(expert FFNs)은 시스템 RAM에 배치합니다. -ngl 999는 모든 것을 GPU로 보내고, --n-cpu-moe 39는 예외적으로 처음 39개 블록의 전문가들을 할당합니다. 샘플링(Sampling) 값은 권장 사항이 아니라 DeepSeek 자체 모델 카드(model-card)의 기본값입니다.
측정된 처리량(Throughput) 아래의 모든 수치는 위 설정으로 1시간 동안 연속 실행한 결과입니다.
| 항목 | 수치 |
|---|
| 생성 (Generation) | 12.0–13.1 t/s |
| 프롬프트 처리 (Prompt processing), 8k–32k 토큰 | 212–224 t/s |
| 프롬프트 처리 (Prompt processing), 1k–5k 토큰 | 153–210 t/s |
| 프롬프트 처리 (Prompt processing), 1k 미만 | 15–115 t/s |
생성 속도는 한 시간 내내 일정했습니다 — 드리프트(drift)나 성능 저하(degradation)가 없었으며, VRAM은 실행 간의 증가 없이 22483–22836 MiB로 안정적이었습니다. 마지막 행은 처리량이 아니라 요청당 고정 오버헤드(fixed per-request overhead)입니다: 41토큰 프롬프트는 15 t/s로 "실행"되며 여전히 3초 이내에 완료됩니다. 작업 부하(workload)가 매우 작은 요청들로 구성된 경우가 아니라면 이 수치는 무시하십시오. 여기서 생성 속도는 GPU나 코어 수에 의한 것이 아니라, CPU가 시스템 RAM에서 활성 전문가(active experts)를 얼마나 빠르게 스트리밍할 수 있는지에 의해 제한될 가능성이 높습니다. 이것이 성능이 매우 안정적인 이유를 설명해 줍니다. 13900K는 하이브리드 부품이며 -t 24 설정은 P-코어(P-cores)와 E-코어(E-cores) 모두를 아우르기 때문에, 빠른 코어가 느린 코어를 기다리게 될 수도 있습니다. 제가 직접 측정하지는 않았지만, 하이브리드 Intel CPU를 사용 중이라면 더 많은 코어가 더 낫다고 가정하기 전에 -t 8과 -t 16을 먼저 시도해 보십시오.
실제로 시간이 어디에 소요되는가: 저는 에이전트 코딩 하네스(agentic coding harnesses, OpenCode, Pi, Qwen Code)를 통해 이를 구동하고 있습니다. 턴(Turn)은 매우 다른 두 가지 형태를 띱니다.
프롬프트 제한적 턴(Prompt-bound turns) — 에이전트가 긴 대화 내용을 다시 읽은 다음, 도구 호출과 같이 짧은 작업을 수행하는 경우입니다. 접두사 캐시(Prefix cache)는 이 경우에 도움이 되지 않았으므로 전체 컨텍스트가 다시 처리되었습니다:
| 컨텍스트 재처리 (Context reprocessed) | 프롬프트 평가 (Prompt eval) | 생성 (Generation) | 시간 (Time) | 프롬프트에 소비된 비중 (Share spent on prompt) |
|---|
| 32284 tok | 146 s | 303 tok | 25 s | 85 % |
| 28403 tok | 127 s | 263 tok | 21 s | 86 % |
| 18862 tok | 89 s | 256 tok | 21 s | 81 % |
이 함축적 의미를 주목하십시오: 첫 번째 토큰이 나오는 데 2분 30초가 걸릴 수 있습니다. 응답이 1분 이내에 시작될 것이라고 가정하는 클라이언트는 서버가 정상적으로 작동하는 동안 연결을 끊어버릴 것입니다.
생성 제한적 턴(Generation-bound turns)은 그 반대입니다: 한 턴에서 3358토큰 프롬프트를 18초 만에 처리한 후 4610토큰을 연속으로 생성했습니다 — 378초가 소요되었으며, 프롬프트 평가(prompt eval)는 턴의 5%만을 차지했습니다. 전체 파일을 작성할 때 12 t/s의 속도가 실제로 고통스럽게 다가옵니다.
실제 작업에 소요되는 시간
세 가지 서로 다른 에이전트 하네스(agent harnesses)를 사용하여 동일한 작업을 각각 한 번씩 실행했습니다. 각 에이전트는 코드를 작성하고, 실행하고, 보고서와 도표를 생성해야 했습니다. 이는 멀티 턴(multi-turn), 수십 번의 도구 호출(tool calls), 그리고 약 30k 토큰까지 늘어나는 컨텍스트(context)를 포함합니다.
| 하네스 | 실제 소요 시간(wall clock) |
|---|
| Opencode | 896초 완료 |
| Pi | 1088초 완료 |
| Qwen Code | 1570초 완료 |
12 t/s의 속도로 전체 에이전트 작업(agentic task)을 수행하는 데 15분에서 26분이 소요되었습니다. 이것이 "사용 가능한가요?"라는 질문에 대한 솔직한 답변입니다. — 네, 키보드 앞에서 잠시 자리를 비울 용의가 있다면 가능합니다. 하네스 간의 편차는 서버 튜닝을 통해 얻은 그 어떤 결과보다 컸으며, 이는 설정을 조정하며 저녁 시간을 허비하기 전에 반드시 알아두어야 할 사실입니다.
튜닝 순서
- 컨텍스트가 실제로 가득 찼을 때(로드 시점이 아닌 실제 사용 시점) OOM(Out of Memory)이 발생하지 않는 가장 낮은
--n-cpu-moe 값을 찾으세요.
- 로딩 시점이 피크(peak)가 아닙니다. 그 다음, 남은 VRAM만큼
-ub를 높이세요.
-b >= -ub를 유지하세요.
-c 또한 메모리 조절 노브(knob)입니다. 컨텍스트를 절반으로 줄이면 많은 양의 KV 캐시(KV cache)를 확보할 수 있으며 생성 속도에는 영향을 주지 않으므로, 레이어(layers)를 CPU로 넘기기 전에 이 방법을 먼저 시도해 보세요.
- 이 구성에서는
--no-mmap이 실질적인 역할을 합니다. 전문가 텐서(expert tensors)는 매 토큰마다 읽히는데, 이들이 페이지 캐시(page-cache)에 의해 관리되어 교체(evictable)되는 상황을 원치 않기 때문입니다. 60초의 로딩 시간은 그에 따른 대가입니다.
- 도구 호출(tool calling)을 수행한다면
--jinja는 선택 사항이 아닙니다. 모델 자체의 채팅 템플릿(chat template)이 없으면 모델의 능력이 부족한 것처럼 보이는 이상한 오류가 발생합니다.
제가 주장하지 않는 것
단일 머신, 단일 양자화(single quant), 단일 워크로드입니다. 여기에는 품질 벤치마크(quality benchmarks)가 포함되어 있지 않으며, 오직 처리량(throughput) 및 적합성 보고서일 뿐입니다. 만약 동일한 그래픽 카드를 사용하지만 RAM 사양이 다르다면, 비교해야 할 흥미로운 지표는 생성 수치(generation number)가 될 것입니다.
/u/HomoAgens1 제출 [링크] [댓글]