Luce Spark: 16GB GPU에서 오프로드 부담 없이 돌리는 35B MoE 모델
Luce Spark: a 35B MoE on a 16 GB GPU, without the offload tax
핵심 요약
GPU 메모리 부족 문제를 해결하기 위해 자주 쓰이는 전문가 모델만 GPU에 상주시키는 효율적인 MoE 추론 기술입니다.
- 메모리 최적화 — 35B MoE 모델을 16GB GPU에서 오프로드 부담 없이 구동함
- 전문가 캐싱 — 활성 전문가만 GPU에 유지하고 나머지는 RAM에서 동적으로 교체함
- 자체 튜닝 — 별도의 오프라인 보정 없이 실시간 라우팅을 통해 최적의 배치를 학습함
- 성능 유지 — 융합 그래프 방식을 사용하여 오프로드 시에도 높은 토큰 처리 속도를 유지함
안녕 라마들아, 너희 시간은 소중하니까 핵심만 짧게 말할게 (최대한 다 설명해보려고 노력은 해볼게 ㅋㅋ).
세 줄 요약:
- 16GB GPU에서 33-35B MoE 구동 가능. Qwen3.6 35B-A3B: 13.3 GiB (원래는 약 20.5). Laguna XS.2 33B-A3B: 14.6 GiB (원래는 18.8). 둘 다 RTX 3090에서 측정했고, 16 GiB 미만으로 들어옴.
- 활성화된 전문가(expert)만 GPU에 상주. A3B 모델은 토큰당 256개 전문가 중 약 8개를 호출함. Spark는 어떤 전문가가 자주 쓰이는지 알아서 학습하고 걔네만 GPU에 박아둠. 나머지는 시스템 RAM에 있다가 필요할 때마다 GPU 캐시로 교체됨.
- 자동 튜닝. 실시간 라우팅을 보면서 어디에 배치할지 스스로 학습하고 모델 옆에 저장함. 재시작할 때마다 더 최적화된 프로필을 불러옴. 별도의 코퍼스나 오프라인 캘리브레이션 작업 필요 없음.
- 명령어 하나로 백엔드 통합.
dflash_server <model.gguf> --spark치면 laguna랑 qwen35moe 둘 다 돌아감. 서버가 알아서 캐시 사이즈 잡고, 학습된 프로필 있으면 불러오고, 계속 유지함. - 속도 저하 없는 오프로드. 오프로드 상태에서도 laguna는 토큰 하나를 40개의 레이어별 그래프가 아니라 **하나의 융합된 그래프(fused graph)**로 처리함. GPU에 다 올라갔을 때랑 비트 단위로 똑같고 속도도 똑같음 (119 tok/s). 60%만 올려도 약 100 tok/s 나옴 (그냥 오프로드했을 때 66 tok/s보다 1.5배 빠름).
오픈소스니까 여기서 확인해봐: https://github.com/Luce-Org/lucebox-hub (Apache2.0).
이게 뭐 마법 같은 건 아님. 전문가 오프로딩은 원래 있던 개념이야. llama.cpp도 지원하고(--n-cpu-moe / --cpu-moe), ktransformers나 ik_llama.cpp도 다 함. 자주 쓰는 전문가를 GPU에 두고 나머지는 RAM에 두는 건 흔한 트릭이지.
작동 원리는 크게 세 가지야:
- 캘리브레이션된 배치. Spark는 실제 요청에서 (레이어, 전문가)별 호출 빈도를 쌓아서 제일 많이 쓰는 애들을 고정함. 테스트해보니까 콜드 히트율이 (균등 분할 시) 36%에서 7% 정도로 확 줄더라.
- 제한된 비동기 캐시. GPU에 고정된 여유 슬롯을 둠. 콜드 전문가가 호출되면 호스트 메모리에서 비동기로 가중치를 복사해오는데, 연산이랑 겹쳐서 처리하고 LRU(가장 오래된 것)를 밀어냄. 미스가 나도 멈추는 게 아니라 처리량만 좀 줄어드는 식임. 링 구조라서 스왑할 때 가중치 텐서 3개 복사하고 라우팅 엔트리 하나 업데이트하면 끝이라 별도의 복잡한 경로도 없음. 둘 다 같은 메커니즘을 씀.
- 하나의 융합된 그래프. 기존 오프로드 방식은 토큰당 40개의 레이어별 그래프를 만들었음. 이걸 어텐션 그래프에 FFN을 합쳐서 토큰 하나를 통째로 돌리니까 오버헤드가 싹 사라짐. 다 올렸을 때 융합된 디코딩은 올 GPU랑 비트 단위로 똑같고(128/128 토큰, spark/bench.py로 검증함) 속도도 똑같이 119 tok/s 나옴.

