GPU 없이 13년 된 Xeon에서 Gemma 4 26B를 초당 5토큰으로 실행하기
(neomindlabs.com)- 2013년형 듀얼 Xeon E5-2690 v2와 DDR3로 구성된 서버에서 Gemma 4 26B-A4B Q8_0을 CPU만으로 구동해 디코딩 약 5.2토큰/초, 프롬프트 평가 약 16토큰/초를 달성함
ik_llama.cpp의 고속 경로는 AVX2·FMA3를 전제로 하지만 Ivy Bridge CPU는 AVX1만 지원하므로, 비 AVX2 빌드를 위한 컴파일 수정과 연산 폴백이 필요했음- 그래프 빌더가
MOE_FUSED_UP_GATE와FUSED_UP_GATE를 무조건 생성하는 반면 비 AVX2 디스패처에는 처리 경로가 없어, 순전파마다 약 240개 텐서가 계산되지 않은 채 난삽한 다국어 출력으로 이어짐 - Claude가 로짓 계측과 코드 분석으로 오류를 찾아 융합 연산을 두 번의
ggml_mul_mat_id와ggml_fused_mul_unary로 대체했으며, 사용자는 실험을 실행하고 정상 결과의 기준을 판별함 - 오래된 기업용 서버도 유료 API 장애 시의 로컬 대체 수단이나 느린 배치 작업에 활용할 수 있지만, AVX2 전용 레이아웃을 만드는
--run-time-repack은 사용하면 안 됨
13년 된 스토리지 서버의 실행 환경
- 재활용한 HP StoreVirtual 장비는 2013년형 듀얼 Xeon E5-2690 v2와 DDR3 메모리를 사용하며 GPU가 없음
- Ivy Bridge 세대라 AVX1만 지원하고 AVX2와 FMA3는 지원하지 않음
- 원래 디스크 저장용으로 제작됐으며 구입 비용은 300달러 미만임
- 실행 모델은 Google의 Gemma 4 26B-A4B로, 260억 파라미터를 가진 오픈 가중치 전문가 혼합(MoE) 모델임
- Q8_0 양자화 모델에서 디코딩은 약 5.2토큰/초, 프롬프트 평가는 약 16토큰/초로 측정됨
출발점이 된 2016년형 Xeon 사례
- Hacker News에서 공유된 A 10 year old Xeon is all you need는 GPU 없이 2016년형 단일 Xeon과 128GB DDR3에서 Gemma 4를 실행한 사례임
- 해당 구성은 ik_llama.cpp와 약 25개의 세밀한 실행 플래그를 사용함
- 추측 디코딩
- CPU를 고려한 MoE 라우팅
- CPU용 플래시 어텐션
- 실행 시간 가중치 재패킹
- 같은 접근을 Ivy Bridge 서버에 적용했지만 시작 단계에서 실행이 중단됨
- 2016년형 Broadwell CPU와 달리 E5-2690 v2에는 AVX2와 FMA3가 없음
- 이 명령어 집합은 2014년 Haswell, 즉 Intel의 v3 세대부터 제공됐으며 고속 커널은 이를 전제로 작성돼 있었음
Claude를 이용한 진단과 패치
- 시작 실패 정보를 전달받은 Claude는 CPU 명령어 집합 차이를 원인으로 특정함
- 앞서 무료 모델로 시도했던 미완성 접근을 이어받아, 성능상 중요한 C++ 경로가 AVX2 이전 CPU에서 올바르게 폴백하도록 수정함
- 작업은 단일
fix it요청으로 끝나지 않았음- 다른 개발자가 작성한 성능 중심 C++ 코드를 읽음
- 특정 마이크로아키텍처에서 커널이 유효하지 않은 이유를 분석함
- 포크의 기존 최적화를 버리지 않으면서 지원되지 않는 경로를 우회함
- 사용자는 C++ 커널 폴백을 직접 작성하는 대신 실험을 실행하고 출력을 읽으며 다음 질문을 정하고, 정상 결과의 기준을 판별하는 역할을 맡음
- 진단과 패치는 해당 서버에서 실행된 Claude 인스턴스가 수행함
비 AVX2 빌드에서 깨진 연산 경로
- Gemma 4 MoE 추론에 사용한
ik_llama.cpp는llama.cpp포크이며, 기본적으로 AVX2를 최소 조건으로 가정함 - 빌드할 때
GGML_USE_IQK_MULMAT를 끄면 대부분의 고속 경로가 제외되고 일반 스칼라/SSE 연산으로 폴백함- 일반적인 Q8_0 행렬 곱셈에는 이 폴백이 작동함
- 다만 두 그래프 연산에는 폴백이 적용되지 않았음
- Gemma 4의 MoE 피드포워드 네트워크는 다음 연산을 생성함
MOE_FUSED_UP_GATE: 전문가별 gate·up 행렬 곱셈과 SwiGLU를 결합한 연산FUSED_UP_GATE: 비 MoE 계층에서 사용하는 밀집 연산 버전
- 컴퓨트 디스패처의 두 연산은
GGML_USE_IQK_MULMAT조건으로 보호됐지만, 그래프 빌더는 조건 없이 연산을 생성함- 비 AVX2 빌드의 디스패처에는 해당 enum을 처리하는
case가 없었음 - 연산이 기본 분기로 빠지면서 모든 전문가 피드포워드 네트워크의 목적지 텐서가 조용히 계산되지 않음
- 비 AVX2 빌드의 디스패처에는 해당 enum을 처리하는
- Gemma 4 26B는 30개 계층에서 토큰당 활성 전문가 8개를 사용하므로, 순전파마다 메모리 버퍼에 남아 있던 값이 담긴 텐서 약 240개를 소비하게 됨
난삽한 출력에서 드러난 단서
- 오류 출력은 유창해 보이지만 의미 없는 다국어 문자열이었음
- 26만 2,000개 어휘 전체에 토큰 ID가 고르게 퍼짐
- 태국어, 한국어,
<unused>센티널, 영어 조각 등이 비슷한 빈도로 생성됨
- 온도 0에서 출력은 결정적이었고, 단일 스레드와 다중 스레드 실행 결과도 바이트 단위로 같았으며 NaN은 발생하지 않음
- 계층마다 큰 상수가 은닉 상태를 밀어 최종 소프트맥스가 평평해지는 형태를 보임
- Claude는 샘플링 전 원시 로짓을 계측해 상위 5개 토큰, 범위, 평균, NaN 수를 출력함
- 첫 예측 토큰의 평균 로짓이 0 근처가 아니라 +16이었음
- 전체 어휘의 약 80%가 양의 로짓을 가졌음
- 무작위 손상과 달리 편향이 일정했기 때문에, 은닉 상태의 큰 부분이 작은 양의 부동소수점 값이 남은 초기화되지 않은 메모리를 사용한다고 범위를 좁힘
세 단계로 구성된 수정
- 패치는 포크의
main위에 세 개 커밋으로 구성됨 -
비 AVX2 컴파일 수정
iqk_quantize.cpp의quantize_row_q8_0_x4와quantize_row_q8_1_x4_T에 있는 스칼라#else분기가 실제로는hsum_i32_8등 AVX2 도우미를 참조하고 있었음- 해당 분기를 이식 가능한 스칼라 루프로 다시 작성함
ggml.c와ggml-quants.c로 새어 나온 일부 IQK 호출에#if GGML_USE_IQK_MULMAT보호 조건을 추가함iqk_cpu_ops.cpp가 독립적으로 컴파일되도록 누락된 include를 추가함- 이 수정이 없으면 포크 자체가 비 AVX2 하드웨어에서 빌드되지 않음
-
실행 시간 그래프 폴백
- 디스패처를 고치는 대신 그래프 빌더가 해당 빌드에서 이미 계산 경로를 가진 연산을 생성하도록 변경함
ggml_moe_up_gate에서GGML_USE_IQK_MULMAT가 꺼져 있을 때 결합된up_gate_exps가중치를 처리함- 텐서 형태는
[n_embd, 2*n_ff, n_experts]이며 앞 절반은 gate, 뒤 절반은 up임 - 두 개의
ggml_view_3d슬라이스로 분리함 - 각 슬라이스에
ggml_mul_mat_id를 실행함 ggml_fused_mul_unary(gate, up, SILU)로 두 결과를 결합함- gate와 up 가중치가 이미 분리돼 있다면 슬라이스 없이 두 번의
ggml_mul_mat_id와 융합 곱셈·단항 연산을 사용함 - 비 MoE 계층에서 사용하는
ggml_fused_up_gate에도 같은 폴백을 적용함 mul_mat_id는 기본 ggml 구현을 사용하고fused_mul_unary는 SILU와 곱셈을 한 번에 처리하므로, 모든 구성 연산에 비 IQK 구현이 이미 존재함- 전체 변경은
#if !GGML_USE_IQK_MULMAT뒤에 있어 AVX2 빌드 결과는 기존과 비트 단위로 같음
-
CI 스텁 정비
- IQK 소스의
#else스텁이iqk_mul_mat.h와 달라 비 AVX2 하드웨어에서ci/run.sh도 빌드되지 않았음 <cstdint>include가 빠져 있었음- 일부 스텁은 불필요한 선행 매개변수를 갖거나
sinks매개변수가 누락되는 등 시그니처가 달랐음 - 일부 함수는 스텁 자체가 없어 링크 단계에서 정의되지 않은 참조가 발생함
- 스텁을 헤더와 맞추면서 비 AVX2 환경에서도 테스트 스위트 실행이 가능해짐
- IQK 소스의
폴백의 성능 비용과 재패킹 오류
- 폴백은 하나의 융합 커널 대신 두 번의
mul_mat_id를 실행하므로 추가 비용이 발생함 - 해당 CPU는 이미 메모리 대역폭 제약을 받고 있고 원래 융합 커널도 AVX2 전용이어서, 이 환경에서 포기하는 기존 실행 경로는 없었음
- 최종 성능은 26B-A4B MoE에서 디코딩 약 5.2토큰/초, 프롬프트 평가 약 16토큰/초임
--run-time-repack은 시작할 때 양자화 가중치를 AVX2 전용 인터리브 형식인Q8_0_R8로 재배열함- AVX1 환경에서 출력을 다시 손상시키는 별도 버그임
- 현재 패치는 이를 수정하지 않으며 실행 스크립트에서 해당 플래그를 제거함
원인을 좁힌 과정
- 명령어 집합 불일치는 쉽게 확인됐지만, 디스패처가 오류 없이 기본 분기로 빠지는 문제는 찾기 어려웠음
- 코드 검토를 통해 여러 후보를 제거함
- RMSNorm 도우미는 올바르게 보였음
ggml_vec_dot_q8_0_q8_0의 AVX1 폴백도 올바르게 보였음- 단일 스레드 결과가 비트 단위로 같아 스레딩 오류를 배제함
- 로짓 평균이 +16에 고정되고 긴 꼬리의 토큰들이 비슷한 값을 가진다는 점에서 잔차 스트림의 큰 부분이 초기화되지 않았다고 판단함
- 디스패처에서
#if GGML_USE_IQK_MULMAT를 검색한 뒤 약 1분 만에 누락된 두 연산 경로를 찾음
재현 조건과 활용 범위
- AVX2 이전 장비의 재현 조건은 다음과 같음
- 하드웨어: 듀얼 Xeon E5-2690 v2, Ivy Bridge, AVX1, DDR3, GPU 없음
- 빌드: 패치 브랜치의
ik_llama.cpp를GGML_USE_IQK_MULMAT없이 컴파일 - 모델: Gemma 4 26B-A4B Q8_0
- 실행: 일반적인
ik_llama.cppCPU 플래그를 사용하되--run-time-repack은 제외
- 정확한 변경은 ikawrakow/ik_llama.cpp PR #2138에서 확인할 수 있음
- 작성 시점에는 아직 열려 있고 관리자 검토를 기다리는 상태라 브랜치에서 직접 실행해야 함
- 같은 장비에서 발생한 버그는 PR 스레드에 보고할 수 있음
- 오래된 기업용 서버에 로컬 모델을 유지하면 유료 API가 중단됐을 때 대체 수단으로 쓰거나, 토큰당 과금이 맞지 않는 느린 배치 작업을 처리할 수 있음
- 구독 서비스 이용보다 낯선 코드와 오래된 시스템을 직접 파고드는 능력을 중시하며, 이는 15년 된 Rails 애플리케이션이나 담당자가 떠난 데이터베이스를 유지하는 작업에도 같은 방식으로 적용됨
댓글과 토론
Hacker News 의견들
-
2027년 중반이면 2,000억 개 초과 전문가 혼합(MoE) 모델을 일반 소비자용 하드웨어에서 구동할 수 있으리라 예상함
16GB Mac에서 Qwen3.6-35B-A3B를 로컬로 돌리며 초당 7~9토큰을 얻고 있음: https://github.com/deepanwadhwa/samosa-chat
16GB RAM MacBook Air에서 GPT-4급 모델이 이 정도 속도로 로컬 실행되는 셈임- 그때까지 기다릴 필요도 없을 듯함. Prism이 며칠 전 공개한 3진 가중치 모델 Bonsai 27B는 약 7GB에 불과하고 M4 Max 노트북에서 초당 44토큰 이상을 냄: https://huggingface.co/prism-ml/Ternary-Bonsai-27B-mlx-2bit
이미 대다수 2,000억 개 이상 모델의 활성 매개변수 수와 비슷한 범위라 Prism이 마음만 먹으면 그런 모델을 내놓을 수 있음. 다만 HRM 같은 재귀 신경망은 매개변수가 그만큼 많이 필요하지 않으므로, 정말 그런 규모가 필요한지는 논쟁의 여지가 있음: https://huggingface.co/sapientinc/HRM-Text-1B - 초당 7~9토큰은 괜찮은 속도라 보기 어려움. 전문가까지는 아니지만 로컬에서 실험해 보니 초당 12~16토큰보다 느리면 답답했음
- 예측에는 대체로 동의하지만 시점은 조금 더 늦을 수 있다고 봄. 이런 성과를 내려면 현재처럼 매개변수당 비트 수를 줄이는 것과는 전혀 다른 압축이 필요하므로, 그 상황에서는 기존의 매개변수 개수라는 척도 자체가 의미 없을 수 있음
가령 계층마다 256비트 시드 하나만 두고 이를 잡음 함수에 넣어 16K개의 실제 가중치를 생성하면, 가중치 하나당 저장 크기를 1비트 미만으로 낮출 수 있음 - Ornith 35B를 Pi로 돌려 초당 50토큰 이상을 얻고 있음. Pi가 검색과 가져오기도 지원한다는 걸 안 뒤로는 검색용으로 대형 모델을 찾을 필요가 없어졌음
이번 달과 다음 달에 판도를 바꿀 새 모델들이 연달아 나올 듯해 기대됨. Ornith는 꼭 써볼 만함 - 초당 9토큰이면 견디기 어렵지 않나 싶음. Claude 세션에서 하루도 안 돼 100만 토큰을 쓰는 일이 흔한데, 실제 작업에는 너무 느려 보임
- 그때까지 기다릴 필요도 없을 듯함. Prism이 며칠 전 공개한 3진 가중치 모델 Bonsai 27B는 약 7GB에 불과하고 M4 Max 노트북에서 초당 44토큰 이상을 냄: https://huggingface.co/prism-ml/Ternary-Bonsai-27B-mlx-2bit
-
듣기 싫어하는 사람도 있겠지만, 추론 제공업체의 토큰 비용이 로컬 구동 전기료보다 저렴하다고 봄
단순화를 위해 출력 생성만 계산하면 초당 5토큰은 시간당 18,000토큰이며, 제공업체 비용은 약 0.005달러임. 서버가 추론 중 약 500W를 쓴다고 보고 전력 요금이 kWh당 0.3달러인 독일을 기준으로 하면, 같은 양을 로컬에서 생성하는 데 0.15달러가 들어 30배 비쌈
개인정보가 걱정된다면 로컬 실행이 여전히 좋지만, 추론 제공업체보다 훨씬 비효율적이라는 점은 알아야 함. 새 GPU가 추론 효율을 높이면서 이 격차도 크게 벌어질 것임
처음에는 18만 토큰으로 잘못 계산했지만 실제로는 18,000토큰이므로, 전기를 거의 공짜로 쓰지 않는 한 경쟁하기 어려움. 제공업체들도 소형 모델에 아직 H200/H100을 쓸 텐데 GB300이나 내년 Ruby GPU로 바꾸면 추론비가 30분의 1로 내려가 로컬 모델의 주된 가치는 개인정보 보호가 될 듯함- 집에서 Qwen 27B를 구동하면 작업 중 약 400W를 소비하고, 생성은 초당 약 40토큰이며 더 중요한 프롬프트 처리는 초당 약 1,000토큰임
한 시간이면 360만 입력 토큰을 처리하거나 144,000토큰을 생성하며 전기료는 약 0.15달러임. Sonnet으로 같은 양을 처리하면 입력은 7.2달러, 생성은 1.4달러이므로 클라우드가 생성에서 10배, 처리에서는 거의 50배 비쌈 - 미국에서는 kWh당 0.30달러에 근접하지도 않음. 사용량이 적은 시간대에는 그 절반이고, 배터리에 1,000달러를 투자해 초저가 시간대의 0.11달러 전기를 저장할 수도 있음
추론 제공업체들은 막대한 부채를 안고 시장점유율 경쟁 중이므로 가격은 분명 오를 것임 - 태양광과 배터리로 작동하는 독립형 자가 호스팅 LLM 서버를 만들면 멋질 듯함. Low Tech Magazine처럼 햇빛이 부족할 때는 오프라인이 되고, 친구 모임·거리·동호회 등 지역 공동체가 매일 쓰기에 필요한 규모로 구축하는 방식임
AI를 공동체가 직접 통제할 만큼 민주화하면 데이터센터 문제도 풀고, 검열과 정렬 수준도 공동체가 민주적으로 정할 수 있음. Geohotz의 일부 글과 비슷한 구상임
오픈소스 모델은 곧 중고 하드웨어로 저렴하게 서비스할 만큼 좋아지고 효율적이 될 것임. 작은 공동체마다 기술에 밝은 사람 한 명이 수백 달러의 초기 비용을 모으면 이후에는 전기료 없이 거의 무료로 운영할 수 있음
https://solar.lowtechmagazine.com/ - 효율도 중요하지만 전기가 저렴하거나 효율적인 장비를 가진 사람도 많음. AMD Strix Halo 홈 서버에서는 100W만 사용하면서 Gemma4-26B를 대략 초당 70토큰으로 제공할 수 있음
- 비용이 더 드는지는 신경 쓰지 않음. 로컬로 돌리는 이유는 돈을 아끼기 위해서가 아니라 자유와 개인정보 보호를 얻기 위해서이며, 선택지가 존재하면 장기적으로 비용도 낮아짐
로컬이라는 대안이 없다면 클라우드 모델 가격은 훨씬 비쌀 것임
- 집에서 Qwen 27B를 구동하면 작업 중 약 400W를 소비하고, 생성은 초당 약 40토큰이며 더 중요한 프롬프트 처리는 초당 약 1,000토큰임
-
이 세대의 듀얼 Xeon은 부하가 걸리면 300W 이상을 소비할 가능성이 큼. 미국 평균 전기료로 하루 1.35달러이며, 여름에 공간을 냉방해야 한다면 더 들어감
프롬프트 처리 시간을 무시하고 24시간 돌려도 하루 약 40만 토큰이므로 출력 100만 토큰당 약 0.30달러임. 공교롭게도 현재 OpenRouter에서 이 모델의 가격과 같지만, OpenRouter의 생성 속도는 8배 빠름
데이터가 집 밖으로 나가지 않게 하는 등 로컬 LLM을 실험할 이유는 많지만 금전적으로 이득 보기는 어려움. 집의 로컬 추론 장비에 훨씬 많은 돈을 투자한 입장에서, 재미는 있어도 절약 수단은 아니라고 봄- 실제 주택에 사는 사람이라면 합리적인 계산임. 나는 임대 주택에 살며 전기료를 직접 내지 않으므로 집주인이 항의하기 시작하는 시점이 비용 효율의 경계임
- 대부분은 돈을 아끼려고 모델을 로컬에서 구동하는 게 아니라 개인정보를 퍼뜨리지 않기 위해서라고 봄
- 암호화폐와 비슷함. 전력 요금 때문에 대다수에게는 직접 채굴하는 것보다 구매하는 편이 저렴함
- 집에서 난방을 켜는 추운 계절에는 폐열도 쓸 수 있어 경제성이 더 좋아짐
-
GPU 없이 듀얼 Xeon과 DDR4 256GB에서 여러 모델을 구동한 결과를 정리했음
https://gist.github.com/hparadiz/f3596d00a62d8ebb2dadcc46ee5822c7- NUMA 성능 저하를 없애기 위해 CPU 하나만 사용해 봤는지 궁금함. 메모리를 절반만 쓰게 되겠지만 성능 차이가 얼마나 나는지 알고 싶음
- 느린 RAM이 아주 많으면 소형 모델도 상당히 빠르게 도는 듯함. 이 장비에서 더 큰 모델은 어떻게 작동할지 궁금함
-
꽤 느린 편임. 13년 된 CPU에서도 초당 8~12토큰을 얻고 있으며, 문맥 크기와 다른 설정에 따라 달라질 수 있음
https://news.ycombinator.com/item?id=48354801- Xeon E3-1270 V2 3.50GHz와 오래된 Nvidia Quadro K2200 4GB에서도 초당 8~9토큰이 나옴. Ollama에서 gemma4:e2b와 gemma4:12b-it-qat를 구동하고 있음
- 원 글은 Q8 양자화를 쓰고 여기서는 Q4를 쓰는 차이가 있지 않나?
-
원 글 작성자임. 원래 댓글이 어떤 이유로 신고 처리된 듯함. 수정 사항은 상위 프로젝트의 PR #2138로 열어뒀음: https://github.com/ikawrakow/ik_llama.cpp/pull/2138
-
이 StoreVirtual 장비에는 소프트웨어를 설치하는 데 쓸 만한 포트가 없어 보임. USB 포트 정도만 있는데, 직렬 콘솔을 통해 설치하는 것인지 궁금함
-
같은 구성으로 2013 Mac Pro에서 Gemma 4 26B를 돌리며 초당 약 5토큰을 얻고 있음. 듀얼 그래픽 카드는 여기에는 쓸모없지만 일부 작업에는 충분히 실용적임
- 지난주 충동적으로 원통형 Mac Pro를 eBay에서 120달러에 샀는데, 최근에는 사람들이 내장 GPU로 모델을 초당 20~30토큰에 돌리기 시작했다는 걸 알게 됨
금요일에 도착하면 직접 시험해 볼 생각이라 기대됨
https://echalupa.com/blog/mac-pro-6-1-llama-cpp-firepro-d300-vulkan-ubuntu
https://matthewgribben.com/blog/mac-pro-6-1-llama-cpp-firepro-d700-vulkan-ubuntu - 그 정도로 느린 속도에서는 어떤 작업에 유용한지 궁금함
- 지난주 충동적으로 원통형 Mac Pro를 eBay에서 120달러에 샀는데, 최근에는 사람들이 내장 GPU로 모델을 초당 20~30토큰에 돌리기 시작했다는 걸 알게 됨
-
지하실의 구성을 직접 봤는데 정말 굉장함. 다음에는 3D 프린터도 소개해 주면 좋겠음
-
다소 관련 있는 영상으로, Pentium 4에서 LLM을 구동하며 NetburstGPT라는 별명을 붙였음. 물론 매우 느림
https://www.youtube.com/watch?v=ILV-eu90te8