learn

llama.cpp에서 MoE 모델 VRAM 최적화

llama.cpp에서 MoE 모델 VRAM 최적화

상황

Qwen3.5-35B-A3B-UD-IQ3_XXS 모델을 16GB VRAM GPU에서 llama.cpp로 실행하는 경우.

모델 특성:

  • MoE 구조: 총 파라미터 35B, 추론 시 활성화는 ~3B (Mixture of Experts)
  • IQ3_XXS: 초저비트 양자화 (~3.x bpw), 전체 파일 크기 ~15-16GB

-ot 옵션: expert를 CPU로 오프로드

../llama.cpp/build/bin/llama-server \
  --model ./models/Qwen3.5-35B-A3B/Qwen3.5-35B-A3B-UD-IQ3_XXS.gguf \
  --jinja \
  -ngl 99 \
  -ot ".ffn_.*_exps.=CPU" \
  --ctx-size 16384 \
  --port 8080 \
  --host localhost

-ot ".ffn_.*_exps.=CPU" 의 의미: ffn_.*_exps 텐서(각 레이어의 routed expert 가중치)를 전부 CPU RAM으로 보냄.

MoE 모델에서 VRAM을 가장 많이 먹는 게 바로 이 expert 가중치들이라, 이 방법으로 3GB 수준의 VRAM만으로도 35B급 모델 구동이 가능. 단, 토큰 생성 시 CPU-GPU 간 데이터 이동이 발생해서 끊기는 느낌이 생길 수 있음.


16GB VRAM이면 전체 GPU 오프로드 가능

IQ3_XXS 기준 모델 전체가 ~15-16GB이므로, -ot 없이 실행하면 VRAM에 전부 올릴 수 있음:

../llama.cpp/build/bin/llama-server \
  --model ./models/Qwen3.5-35B-A3B/Qwen3.5-35B-A3B-UD-IQ3_XXS.gguf \
  --jinja \
  -ngl 99 \
  --ctx-size 16384 \
  --port 8080 \
  --host localhost

실행 로그에서 확인:

llm_load_tensors: offloaded XX/XX layers to GPU   ← XX/XX 같으면 전체 올라간 것
llama_kv_cache_init: VRAM kv self = XX.XX MiB     ← KV cache 크기

Qwen3.5-35B-A3B 기준 결과: 모델이 ~13GB, KV cache가 나머지 ~3GB 사용. 16k context도 문제없이 수용됨.

MoE 모델은 attention 레이어가 ~3B 규모 기준이라 KV head 수가 dense 35B 대비 훨씬 적어, KV cache가 생각보다 작음.


정리

| 방법 | VRAM 사용 | 속도 | 비고 | |---|---|---|---| | -ot .ffn_.*_exps.=CPU | ~3GB | 느림, 끊김 | VRAM 부족 시 | | -ot 제거 (전체 GPU) | ~13GB + KV | 빠름 | 16GB면 충분 |

VRAM이 넉넉하다면 -ot 옵션을 제거하는 게 최선.