
RTX 4070 + Qwen 35B: llama.cpp 플래그 하나(--cpu-moe)로 2.8배 속도 향상
요약
llama.cpp의 --cpu-moe 플래그를 사용하여 RTX 4070 환경에서 Qwen 35B 모델의 추론 속도를 2.8배 향상시킨 사례를 소개합니다. MoE 모델의 전문가 레이어를 CPU로 분리 배치함으로써 GPU VRAM 한계를 극복하고 대역폭 효율을 극대화하는 최적화 방법을 다룹니다.
핵심 포인트
- --cpu-moe 플래그 사용 시 Qwen 35B 모델 속도가 12.2에서 34.6 tok/s로 향상
- MoE 전문가 레이어를 CPU에 배치하고 어텐션 등 핵심 연산을 GPU에 유지하여 병목 해결
- Ollama의 밀집(dense) 방식 분할보다 세밀한 MoE 전용 오프로딩이 성능에 유리
- VRAM 용량이 제한적인 환경에서 대규모 MoE 모델을 효율적으로 구동하는 팁 제공
Ollama 기본 설정으로는 RTX 4070 (12 GB) 환경에서 Qwen3.5-35B-A3B 모델을 사용할 때 12.2 tok/s가 나왔습니다. 하지만 두 개의 플래그(flag)를 적용한 llama.cpp로 전환하자 34.6 tok/s를 기록했습니다. 2.8배 향상된 수치입니다.
두 플래그는 -ngl 99 (모든 레이어를 GPU로 오프로드(offload))와 --cpu-moe (MoE 전문가(experts)를 제외한 나머지를 CPU로 처리)였습니다. 하나는 당연한 선택이었지만, 다른 하나가 이 포스트의 핵심입니다.
llama-server -m qwen35.gguf -ngl 99 --cpu-moe -c 4096
저는 왜 이 특정 조합이 35B 모델이 들어갈 수
--cpu-moe (2025년 중반 llama.cpp에 추가됨, 더 세밀한 --n-cpu-moe N 옵션을 위한 전체 CPU 단축키)는 일종의 탈출구입니다. **MoE 전문가 (experts)**를 제외한 모든 레이어를 GPU에 배치하고, 전문가들은 CPU에 남겨두는 방식입니다. 이렇게 하면 대역폭(bandwidth)을 많이 소모하는 부분(attention, KV cache, layer norms, router)은 GPU에 위치하게 되고, 희소한(sparse) 부분(거의 활성화되지 않는 전문가 그 자체)은 CPU에 위치하게 됩니다.
이 머신에서의 결과는 다음과 같습니다:
- 사용된 VRAM: 11.7 GB (12 GB의 95%)
- 생성 속도: 34.6 tok/s (Ollama 기본값 12.2 대비)
Ollama의 자동 로더(autoloader)가 멍청한 것은 아닙니다. 모델의 약 58%는 CPU로, 약 42%는 GPU로 가야 한다는 것을 계산해냅니다. 하지만 Ollama는 모델을 레이어 단위로 나누는 밀집(dense) 방식으로 분할합니다. 그 결과, 대역폭 병목이 발생하는 CPU에는 어텐션(attention) 경로의 절반이 배치되고, 대부분의 시간 동안 유휴 상태로 머무는 GPU에는 전문가의 절반이 배치됩니다. 이는 양쪽의 단점만을 모아놓은 최악의 결과이며, 2.8배의 성능 손실을 초래합니다.
전체 오프로드 스윕 (The full offload sweep)
사람들이 다음에 시도할 플래그는 --n-cpu-moe N입니다. 이 옵션은 N개의 전문가 레이어만 CPU로 오프로드(offload)하고 나머지는 GPU에 배치할 수 있게 해줍니다. 본능적으로는 "GPU가 더 빠르니까, 들어갈 수 있는 만큼 최대한 많은 전문가를 GPU로 다시 옮기자"라고 생각하기 쉽습니다. 하지만 이 역시 틀렸으며, 스윕(sweep) 테스트를 통해 그 차이를 확인할 수 있습니다.
-ngl 99는 고정되어 있습니다. 오직 N 값만 변경됩니다:
--n-cpu-moe | GPU에 있는 전문가 레이어 수 | tok/s (tg128) | Ollama 기본값 대비 |
|---|---|---|---|
| 48 (모든 전문가가 CPU에 있음) | 0 | 34.60 | 2.8배 |
| ... |
단조 감소(Monotonic decay) 양상을 보입니다. 전문가를 GPU로 다시 끌어오는 순간, 실제로 대역폭이 필요한 부분에서 VRAM을 빼앗아 오게 되어 전체 파이프라인의 속도가 느려집니다. 전문가의 절반(24개 레이어)이 GPU로 돌아오는 시점에는 Ollama의 자동 분할 방식보다 더 느려지게 됩니다.
결론은 명확합니다. 128개의 전문가(expert)를 가진 MoE 모델을 12GB 그래픽 카드에서 구동할 때의 최적값은 모든 전문가를 CPU에 두는 것입니다. "들어갈 수 있는 만큼 최대한"이 아닙니다. 전부 다 말입니다.
재현을 원하신다면, 다음 벤치마크 명령어를 사용하세요:
./build/bin/llama-bench -m qwen35.gguf -ngl 99 -ncmoe 48 -n 128 -r 3
-ncmoe 48은 벤치마크 도구에서 --n-cpu-moe 48과 동일한 역할을 하며, 이는 다시 48개 레이어 모델에 대한 --cpu-moe의 명시적 형태입니다. 설정은 같고 이름만 세 가지인 셈입니다. 이 플래그는 MoE 오프로드 의미론에 대한 활발한 반복 작업이 이루어지던 시기에 llama.cpp에 도입되었습니다.
VRAM 계층별 매핑
위의 표를 통해 여러분의 스윗 스팟(sweet spot)을 거의 바로 읽어낼 수 있습니다. 대략 다음과 같습니다:
- 8–10 GB 카드 (RTX 4060 / 3070): 완전한
--cpu-moe사용. 전문가를 GPU에 배치할 여유 공간(headroom)이 없습니다. - 12 GB 카드 (RTX 4070 / 3060 12 GB): 완전한
--cpu-moe사용. 위의 스윕(sweep) 결과가 여러분의 결과값입니다. Q4 35B-A3B 모델의 현실적인 상한선은 34.6 tok/s입니다. - 16 GB 카드 (RTX 4060 Ti 16 GB / 4070 Ti SUPER): 몇 개의 전문가 레이어를 다시 GPU로 돌릴 수 있으며 (N=44 → 4개 레이어를 GPU에 배치), 약간의 이득을 얻을 수 있습니다. 하지만 아주 약간일 뿐입니다. 그 다음 단계부터는 PCIe 버스 전문가 전송(PCIe-bus expert transfers)이 이득을 갉아먹어 성능을 지배하게 됩니다.
- 24 GB 카드 (RTX 4090 / 3090): 모델 전체를 담을 수 있으므로 이 포스팅 전체를 건너뛰셔도 됩니다. 운이 좋으시네요.
Q4 35B-A3B 모델의 경우, "모두 GPU에 배치"하는 것이 "전문가를 CPU에 배치"하는 것보다 나아지는 교차점은 약 24 GB 부근입니다. 그 미만에서는 수학적으로 분산 배치하는 것이 맞습니다.
수치를 급락시키는 세 가지 요소
위에서 언급한 34.6 tok/s는 명령어를 단순히 복사해서 붙여넣는다고 얻을 수 있는 수치가 아닙니다. 세 가지 함정을 제거한 후에 명령어를 실행했을 때 얻을 수 있는 수치입니다.
함정 1: VRAM이 실제로 여유롭지 않다. WSL2는 Windows 측 프로세스와 VRAM을 기꺼이 공유합니다. 만약 Edge가
만약 이러한 측정 우선 튜닝 (measurement-first tuning) — 더 넓은 시스템 하네스 (system harnesses), 빌드 파이프라인 (build pipelines), 그리고 에이전트 루프 (agent loops)에 적용되는 것과 동일한 로직 — 뒤에 숨겨진 완전한 데이터 기반 엔지니어링 패턴을 원하신다면, Harness Engineering Guide가 상세한 내용을 담고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기