---
title: "10년 된 제온 서버로 젬마4 26B를 돌린 미친 로컬 추론기"
published: 2026-06-01T06:38:42.000Z
canonical: https://jeff.news/article/3565
---
# 10년 된 제온 서버로 젬마4 26B를 돌린 미친 로컬 추론기

글쓴이는 2016년형 Intel Xeon E5-2620 v4, DDR3 128GB, GPU 없는 서버에서 Gemma 4 26B-A4B 모델을 읽는 속도로 돌리는 설정을 공개했어. 핵심은 ik_llama.cpp의 투기적 디코딩, MoE 라우팅, 런타임 리패킹, CPU용 Flash Attention 같은 최적화를 끝까지 끌어낸 것임.

## 낡은 서버로 26B급 모델을 돌린다는 말의 의미

- 글쓴이가 쓴 머신은 요즘 기준으로 보면 진짜 구형 서버임
  - CPU는 2016년형 Intel Xeon E5-2620 v4, 8코어 16스레드, 2.10GHz
  - 명령어는 AVX2까지만 있고 AVX-512, AVX-VNNI, BF16 없음
  - 메모리는 128GB지만 DDR3라 최신 노트북 RAM보다 5~6배 느리다고 설명함
  - GPU는 아예 없음. 내장 GPU도 없음

- 그런데 이 장비로 Gemma 4 26B-A4B를 로컬에서 돌림
  - 모델은 약 25.2B 전체 파라미터를 가진 MoE 구조고, 토큰당 활성 파라미터는 약 3.8B
  - 128개 expert 중 8개가 토큰마다 활성화되는 방식
  - 최종적으로 “읽는 속도” 수준으로 텍스트를 생성했다고 주장함

> [!IMPORTANT]
> 이 글의 핵심 수치는 메모리임. 전체 필요 메모리는 약 82GB이고, 그중 모델 가중치가 약 25GB, 262K 컨텍스트용 KV 캐시가 약 56GB임. KV 캐시가 모델보다 더 큼.

## 병목은 CPU가 아니라 메모리 대역폭

- LLM 추론의 디코더 단계는 생각보다 CPU 연산력이 병목이 아님
  - 토큰 하나를 만들 때마다 거대한 가중치를 RAM에서 CPU 캐시로 계속 끌어와야 함
  - CPU는 계산을 끝내고도 다음 가중치가 메모리 버스를 타고 오길 기다리는 시간이 많아짐
  - 글쓴이는 이걸 “memory wall”이라고 부르며, Xeon이든 H100이든 현대 AI 추론의 큰 장애물이라고 설명함

- 그래서 그냥 `ollama`나 기본 `llama.cpp`로 돌리면 답이 안 나옴
  - Ollama는 필요한 모델 지원이 늦거나 없을 수 있고, 성능 조정용 플래그를 충분히 노출하지 않는다고 지적함
  - 기본 llama.cpp도 범용 GPU 사용 사례 중심이라 이 구형 CPU 환경의 최적화를 다 못 끌어낸다는 입장임
  - 결국 `ik_llama.cpp`의 obscure한 플래그를 직접 다뤄야 했음

## 마법 주문처럼 생긴 실행 옵션의 정체

- 실행 커맨드는 거의 “이걸 사람이 외우라고?” 싶은 수준임
  - `--model`, `--model-draft`, `--spec-type mtp`, `--cpu-moe`, `--merge-up-gate-experts`, `--flash-attn on`, `--mla-use 3`, `--run-time-repack`, `--mlock`, `--no-kv-offload` 같은 옵션이 줄줄이 붙음
  - 글쓴이는 블랙박스 도구에서는 이런 줄을 볼 수 없고, 구형 하드웨어에서는 각 플래그가 뭘 하는지 알아야 한다고 말함
  - 더 웃긴 건 일부 플래그는 적용되지 않고 엔진 로그에서 조용히 알려주는 식이라는 점임

```mermaid
sequenceDiagram
    participant 사용자
    participant 드래프터
    participant 검증모델
    participant 시피유캐시
    participant 디디알쓰리메모리
    사용자->>드래프터: 다음 토큰 후보 요청
    드래프터->>시피유캐시: 작은 작업 집합으로 후보 3개 생성
    드래프터->>검증모델: 후보 토큰 전달
    검증모델->>디디알쓰리메모리: 큰 가중치 스트리밍
    검증모델->>시피유캐시: 후보 검증 계산
    검증모델->>사용자: 승인된 토큰 출력
```

## 투기적 디코딩이 CPU에서 더 맛있는 이유

- `--spec-type mtp --draft-max 3 --draft-p-min 0.0 --spec-autotune` 조합이 핵심임
  - 작은 drafter가 최대 3개 토큰을 먼저 제안하고, 26B verifier가 이를 검증함
  - `--spec-autotune`은 워크로드에 맞춰 체인 길이를 자동 조정함
  - 숨겨진 reasoning token이 많아도 결국 토큰마다 디코더 패스를 돌아야 하니, 이 최적화가 체감 성능에 직접 영향을 줌

- CPU에서는 이 방식이 특히 유리하다고 설명함
  - 작은 drafter의 활성 레이어는 L3 캐시에 들어갈 수 있음
  - 반대로 verifier는 캐시를 훨씬 넘어서는 가중치를 계속 RAM에서 끌어와야 함
  - CPU 연산 몇 번 더 쓰는 비용보다 큰 모델 가중치를 매번 스트리밍하는 비용이 더 비싸다는 얘기임

## MoE 라우팅과 캐시 친화성

- `--cpu-moe --merge-up-gate-experts -t 8 --parallel 8`은 CPU 캐시 구조에 맞춘 MoE 최적화임
  - GPU는 HBM이라는 빠른 메모리 풀을 쓰지만, CPU는 L1/L2/L3 캐시에 크게 의존함
  - MoE 모델이 128개 expert 사이를 마구 뛰어다니면 캐시가 계속 비워지고 DDR3에서 다시 읽어야 하는 cache thrashing이 생김
  - `--cpu-moe`는 expert 선택과 라우팅을 CPU 캐시 계층에 맞추려는 옵션임

- `--merge-up-gate-experts`는 두 번 할 일을 한 번으로 합치는 쪽에 가까움
  - expert 내부의 up projection과 gate projection을 별도 matmul로 처리하지 않고 하나로 융합함
  - 로그에는 `fused_up_gate = 1`로 적용이 확인됐다고 함
  - 메모리 버스를 두 번 왕복할 일을 줄이는 소프트웨어 트릭인 셈

- 스레드도 일부러 8개만 씀
  - 머신은 16 SMT 스레드지만 물리 코어는 8개
  - 메모리 병목 워크로드에서는 스레드를 더 늘려도 DDR3 대역폭이 늘지 않음
  - 오히려 스케줄링 비용만 늘 수 있어서 `-t 8`로 물리 코어에 맞춘 것임

## 메모리 고정, 리패킹, KV 캐시

- `--run-time-repack`은 시작할 때 가중치 행렬을 CPU가 좋아하는 레이아웃으로 다시 배치함
  - 로그상 265개 tensor가 repack됐다고 함
  - 실행 전에 몇 초를 쓰더라도 추론 중 cache miss를 줄여 메모리 대역폭을 더 잘 쓰겠다는 선택임
  - 구형 DDR3 머신에서는 이런 사소해 보이는 레이아웃 문제가 바로 속도 차이로 이어짐

- `--mlock`은 모델을 RAM에 고정해서 스왑으로 밀려나지 않게 하는 옵션임
  - OS가 27GB짜리 모델 가중치를 디스크로 스왑하면 생성 속도는 사실상 멈춤
  - 다만 리눅스 기본 `RLIMIT_MEMLOCK`이 낮으면 `failed to mlock 27628376064-byte buffer` 같은 경고가 뜰 수 있음
  - 글쓴이는 이게 LLM 문제가 아니라 `ulimit -l` 기본값 문제라고 짚음

> [!WARNING]
> 로컬 LLM에서 스왑은 그냥 느린 정도가 아니라 “왜 멈췄지?” 수준의 성능 폭탄이 될 수 있음. 모델을 RAM에 고정하려면 런타임 플래그뿐 아니라 커널 쪽 memlock 제한도 같이 봐야 함.

- `--no-kv-offload`는 GPU가 없다는 사실을 런타임에 명확히 알려주는 옵션임
  - KV cache는 현재 대화 문맥을 저장하는 단기 기억장치임
  - 보통 엔진은 이걸 GPU로 offload하려고 시도할 수 있는데, 이 머신에는 GPU가 없음
  - 불필요한 하드웨어 탐색이나 에러 가능성을 줄이고 시스템 RAM에 두겠다는 선택임

## 그래프 분할은 아직 안 먹혔지만, 로그가 중요함

- `-sm graph -smgs -sas -mea 256 --split-mode-f32`는 계산 그래프와 메모리 분할 관련 옵션임
  - graph split은 레이어를 순서대로 나누는 대신 레이어 내부 계산을 병렬로 쪼개는 방식에 가까움
  - 목표는 여러 프로세서나 메모리 영역을 동시에 바쁘게 만드는 것
  - 다만 이번 실행에서는 Gemma4 external MTP에서 graph split이 지원되지 않아 layer split으로 자동 변경됐다고 함

- 중요한 건 실패한 플래그도 로그로 확인해야 한다는 점임
  - 글쓴이는 이 옵션을 앞으로 새 버전에서 도움이 될 수 있어 남겨뒀다고 설명함
  - bleeding-edge 추론 엔진은 공식 문서보다 코드와 PR 코멘트가 더 정확한 경우가 많다고도 말함
  - 결국 성능 튜닝은 “옵션 넣었으니 됐겠지”가 아니라 로그를 읽는 작업임

## CPU용 Flash Attention까지 들어감

- `--flash-attn on --mla-use 3`도 실제 적용됐다고 함
  - 로그에서 `flash_attn = 1`, `fused_moe = 1`, `fused_up_gate = 1`이 확인됐다고 적음
  - Flash Attention은 거대한 N×N attention matrix를 RAM에 물리적으로 만들지 않고 블록 단위로 계산해 소비하는 최적화임
  - 원래 GPU 쪽에서 유명한 기법인데, 여기서는 CPU 커널로 구현해 긴 컨텍스트 처리 비용을 줄임

- `--mla-use 3`은 Multi-Head Latent Attention 관련 옵션임
  - 일반적인 KV cache는 토큰이 길어질수록 메모리를 크게 먹음
  - MLA는 key/value 정보를 더 작은 latent 표현으로 압축해 저장하는 구조라고 설명함
  - 이 덕분에 긴 대화나 긴 문서를 다룰 때 KV cache 메모리 부담을 줄일 수 있음

## 결론은 ‘하드웨어보다 이해도’에 가까움

- 이 글은 낡은 서버 자랑글처럼 보이지만 실제 메시지는 더 빡셈
  - 오픈 웨이트 모델을 로컬에서 잘 돌리려면 모델 파일만 내려받는다고 끝이 아님
  - 런타임, quant, drafter, GGUF 메타데이터, CPU 캐시, 커널 제한, 로그까지 봐야 함
  - 글쓴이는 이 복잡한 사용성 장벽을 “usability moat”라고 부름

- 그래도 성과는 꽤 인상적임
  - 2016년형 단일 Xeon, DDR3 RAM, GPU 없음
  - 25B급 MoE 모델
  - MTP drafter를 붙인 speculative decoding
  - 약 82GB 메모리 풋프린트
  - 결과적으로 읽는 속도의 로컬 생성

---

## 기술 맥락

- 이 글에서 선택한 핵심 전략은 GPU를 포기하는 대신 CPU의 캐시와 메모리 배치를 끝까지 맞추는 거예요. 왜냐하면 이 환경에서는 연산 장치가 부족해서 느린 게 아니라, DDR3에서 거대한 가중치를 계속 끌어오는 비용이 훨씬 크거든요.

- Speculative decoding을 붙인 이유도 같은 맥락이에요. 작은 drafter는 L3 캐시에 들어갈 만큼 가볍고, 큰 verifier는 매번 메모리를 크게 읽어야 해요. 그래서 작은 모델이 후보를 먼저 뽑고 큰 모델이 한 번에 검증하면, 느린 메모리 왕복을 줄일 수 있어요.

- MoE 최적화는 모델 구조를 하드웨어에 맞춘 선택이에요. Gemma 4 26B-A4B는 전체 expert를 다 쓰지 않고 토큰마다 일부만 쓰는데, expert 선택이 흩어지면 CPU 캐시가 계속 깨져요. `--cpu-moe`와 fused expert 연산은 이 캐시 낭비를 줄이려는 시도예요.

- `--mlock`과 `--run-time-repack`은 운영체제와 메모리 레이아웃까지 추론 파이프라인의 일부로 본다는 점에서 중요해요. 모델이 스왑으로 밀려나거나 행렬 배치가 CPU에 안 맞으면, 같은 모델과 같은 CPU라도 체감 속도가 완전히 달라질 수 있거든요.

- 결국 여기서 배울 점은 로컬 AI가 “GPU 있냐 없냐”만의 문제가 아니라는 거예요. 모델 아키텍처, 추론 엔진, OS 제한, 캐시 구조를 같이 봐야 하고, 블랙박스 래퍼가 숨기는 기본값이 성능을 크게 깎을 수 있어요.

## 핵심 포인트

- GPU 없이 2016년형 Xeon E5-2620 v4와 DDR3 128GB만으로 25B급 MoE 모델을 실행함
- 전체 메모리 요구량은 약 82GB이며, 모델 가중치 약 25GB보다 262K 컨텍스트용 KV 캐시 약 56GB가 더 큼
- 성능의 병목은 CPU 연산보다 메모리 대역폭이며, 이를 우회하기 위해 투기적 디코딩과 캐시 친화적 MoE 최적화를 사용함
- Ollama 같은 블랙박스 도구로는 노출되지 않는 25개 안팎의 플래그를 직접 조합해야 했음

## 인사이트

이 글의 재미는 ‘낡은 서버도 AI 된다’가 아니라, 로컬 추론 성능이 결국 모델 파일보다 런타임과 메모리 아키텍처 이해에 달려 있다는 데 있어. 오픈 웨이트 AI의 장벽이 하드웨어 가격만이 아니라 문서 없는 플래그, 조용히 실패하는 최적화, 블랙박스 래퍼라는 점을 제대로 보여줌.
