"Hello, World!" — 2350억 개의 파라미터를 가진 프론티어 모델이 48GB MacBook에서 작동하다
요약
2350억 개의 파라미터를 가진 Qwen3-235B MoE 모델을 48GB MacBook에서 실행하는 데 성공한 실험 기록입니다. SSD에서 전문가(experts)를 토큰 단위로 스트리밍하는 C++ 엔진과 Metal 커널을 활용하여 메모리 한계를 극복했습니다.
핵심 포인트
- 235B 규모의 프론티어 MoE 모델을 일반 소비자용 MacBook에서 구동
- SSD를 활용한 전문가(experts) 토큰 단위 스트리밍 기술 적용
- Metal 커널과 C++ 엔진을 직접 구축하여 메모리 벽 문제 해결 시도
- 4-bit 양자화 및 저수준 최적화 과정에서의 기술적 도전 기록
이 글은 호기심 많은 빌더의 일기 중 두 번째 기록입니다. 첫 번째 기록에서, 독학한 웹 개발자는 위성 엔지니어의 직관을 빌리고, 자신이 작성할 수 없는 C++를 대신 작성해 주는 AI 에이전트와 협력하여 터무니없는 질문을 던졌습니다: 책상 위에 있는 MacBook에서 프론티어 AI (Frontier AI)를 실행할 수 있을까? 그 기사는 470GB의 다운로드가 진행 중인 상태로 끝났습니다. 이번 글은 다르게 끝납니다.
1. 그 순간
당신: 안녕이라고 말해봐.
S-MoE [RAM: 48.0GB | Ring: auto]: Hello, world!
그게 전부입니다. 사실, 이게 이야기의 전부입니다.
Qwen3-235B-A22B-Instruct-2507 — 진정한 프론티어 Mixture of Experts (MoE) 모델이자 2350억 개의 파라미터를 가진, 원래라면 API 키 뒤에 숨겨져 있거나 25만 달러 규모의 GPU 클러스터에서 돌아가야 할 그런 모델이 — 일반 소비자용 MacBook에서 질문에 답했습니다. 증류된 (distilled) 버전도 아니고, 거대 모델의 이름을 빌려 쓴 7B "어시스턴트"도 아닙니다. 웹 개발자와 AI 에이전트가 함께 구축한 C++ 엔진과 Metal 커널을 통해, SSD에서 전문가(experts)들을 토큰 단위로 스트리밍하며 작동하는 실제 235B 모델입니다.
속도는 느립니다. 불완전합니다. 또한 제가 알기로는, 아무도 이와 같은 방식으로 해낸 적이 없는 일입니다. 그리고 제가 할 수 있는 가장 정직한 일은 무엇이 필요했는지 정확히 말씀드리는 것이라고 생각합니다. 왜냐하면 우리와 "Hello, world!" 사이를 가로막고 있던 마지막 버그는 GPU 커널에 있었던 것이 아니었기 때문입니다. 그것은 _웹 개발자_라면 뼛속 깊이 알고 있는 종류의 버그였습니다.
2. 수치로 보는 현실
| 항목 | 현실 |
|---|---|
| 모델 | Qwen3-235B-A22B-Instruct-2507 (Apache 2.0) |
| ... |
네, 마지막 줄을 제대로 읽으신 게 맞습니다. 이것은 이메일을 쓰기 위해 사용하는 챗봇이 아닙니다. 이것은 존재 증명입니다: 메모리 벽 (memory wall)에는 문이 있고, 그 문은 바로 SSD입니다.
3. 핵심을 깨닫게 해준 버그
이 부분이 제가 가장 좋아하는 부분입니다. 왜냐하면 "저수준 코드(low-level code)를 다루는 웹 개발자의 마인드" 실험이 그 가치를 증명한 지점이기 때문입니다.
우리가 모델을 4-bit로 파괴한 후(우리의 첫 2-bit 시도는 미세한 전문가(fine-grained experts)들을 수학적으로 짓뭉개버렸습니다. 모델은 마치 테이블을 두드리는 유령처럼 공백과 문장 부호만을 생성했습니다), 엔진이 돌아갔습니다. I/O가 스트리밍되었습니다. Metal 커널이 웅웅거렸습니다. 은닉 상태 규격(hidden-state norms)은 건강했고, 유한했으며, 94개 모든 레이어에 걸쳐 지루할 정도로 정확했습니다.
그리고 모델은 모든 질문에 다음과 같이 답했습니다:
::
콜론 두 개. 그게 전부였습니다. 2,350억 개의 파라미터를 가진 지능의 거대한 산이 우리에게 문장 부호만을 내놓은 것입니다.
시스템 측면에서의 모든 본능은 '아래'를 가리켰습니다 — 즉, 양자화 해제(dequantisation) 수학, RoPE 회전(RoPE rotations), 링 버퍼 동기화(ring buffer synchronisation) 쪽이었습니다. 심각한 저수준 버그(low-level bugs)는 보통 그런 곳에 존재하기 마련입니다. AI 에이전트와 저는 그 모든 것을 확인했습니다. 짧은 원시 프롬프트(raw prompt)에 대한 탐욕적 디코딩(Greedy decoding)은 결점 없는 영어를 생성했습니다: "Hello! How can I...".
엔진은 결백했습니다.
범인은 상류(upstream), 즉 상상할 수 있는 가장 작고 웹 형태를 닮은 디테일인 **채팅 템플릿(chat template)**에 있었습니다. Qwen3는 두 가지 계보로 출시됩니다 — 오리지널 "thinking" 모델과, 우리가 파괴했던 비-thinking 모델인 Instruct-2507입니다. Thinking 계보의 템플릿은 모든 프롬프트에 <think> 토큰을 주입합니다. 그런데 Instruct-2507 가중치에서 이 두 토큰 임베딩(token embeddings)은 훈련되지 않은(untrained) 상태였습니다 — 일반적인 모든 토큰보다 약 150배 더 작은, 거의 0에 가까운 행(rows)들이 불발탄처럼 어휘 사전(vocabulary)에 자리 잡고 있었습니다. 우리는 매 대화의 시작마다 모델의 귀에 의미 없는 두 음절을 속삭이고 있었고, 잔차 스트림(residual stream)은 접촉하자마자 붕괴해 버린 것입니다.
단 한 줄을 바꿨습니다 — 우리가 파괴했던 것과 동일한 체크포인트에서 토크나이저(tokenizer)를 로드하도록 — 그러자 그 거대한 산이 인사를 건넸습니다.
내가 계속해서 다시 배우고 있는 교훈: 그 무시무시했던 저수준 레이어(low-level layer)는 괜찮았습니다. 문제가 된 것은 설정 불일치(config mismatch), 잘못된 템플릿, 혹은 파이프(pipe)에 의해 조용히 삼켜진 에러 메시지였습니다. 이는 모든 웹 개발자가 설정이 잘못된 스테이징 환경(staging environment)에서 새벽 2시에 사냥해 온 바로 그 종류의 버그였습니다. 나의 본능은 Metal 커널(kernel)을 작성하는 데는 쓸모가 없었지만, 그 주변 시스템을 디버깅하는 데는 진정으로 유용했습니다.
memory_order_acquire펜스(fence)를 작성할 수 있는 에이전트와, 반사적으로 "잠깐, 우리가 제대로 된 페이로드(payload)를 보내고 있는 건가요?"라고 묻는 인간의 이 조합 — 이것이 바로 여기서 진행되는 실제 실험입니다.
4. 16 GB에 대한 솔직한 이야기
원래의 꿈 — 선언문에 담겼던 꿈 — 은 16 GB였습니다. "16 GB의 RAM은 512 GB와 동일한 지능을 제공해야 하며, 단지 속도만 느릴 뿐이어야 한다."
우리는 거의 해낼 뻔했습니다. 그리고 나는 이 일기가 진실되기를 약속했기에, 그 "거의"라는 표현에 대해 정확히 말하고 싶습니다.
아키텍처는 유지되었습니다. 117 GB의 전문가 가중치(expert weights)는 실제로 RAM을 0바이트 점유합니다. 그것들은 포논(phonon) 비유가 약속했던 것처럼, 필요할 때 SSD에서 스트리밍됩니다. 그 주장의 해당 부분은 현실과의 접촉 속에서도 완전히 살아남았습니다.
우리가 줄일 수 없었던 것은 서피스 스카우트(Surface Scout) — 모델 자체의 밀집 백본(dense backbone)으로, 다음에 무엇이 실행될지 예측하기 위해 상주해야만 하는 부분입니다. 235B 프론티어 모델의 경우, 그 백본만 해도 bfloat16 형식에서 약 16 GB의 무게를 가집니다. 그것은 우리가 목표로 했던 기기 전체의 크기 그 자체였습니다. 지나고 보니 16 GB에서 프론티어를 쫓는 것은 다소 위험했습니다. 링 버퍼(ring buffer), KV 캐시(KV-cache), 또는 macOS 자체를 위한 공간이 남지 않을 것이기 때문입니다.
따라서 솔직하게 재조정된 주장은 다음과 같습니다:
이제 32–48 GB MacBook은 235B 프론티어 모델을 로컬에서 실행할 수 있으며, 지능은 저하되지 않고 오직 속도만 저하됩니다. 그리고 16 GB Mac은 동일한 원칙과 동일한 주권 하에, 더 작은 세밀한 MoE 모델들로 동일한 아키텍처를 실행합니다.
저는 이 상황을 받아들이기로 했습니다. 32GB에서의 프론티어 (Frontier) 모델 구동은 지난 1월까지만 해도 공상 과학 소설 같은 이야기였습니다. 이것이 16GB에서의 프론티어 모델 구동이 아니라고 짜증을 내는 것은, 달로 가는 첫 비행에서 다리 공간이 좁다고 불평하는 것과 같습니다.
5. 다음 단계
오늘 "Hello, world!"라고 말하는 이 시스템은 앞으로 존재할 버전 중 가장 느린 버전일 것입니다. 로드맵은 공개되어 있으며 구체적입니다. Scout의 근사치 대신 무거운 모델 자체의 은닉 상태 (hidden state)로부터 컴퓨팅 전문가 라우팅 (computing expert routing)을 수행하고, GPU의 waitUntilCompleted를 MTLSharedEvent 파이프라이닝 (pipelining)으로 교체하며, 궁극적으로는 아주 적은 비용으로 활성화 (activations)를 예측하는 작은 증류된 (distilled) Scout를 만드는 것입니다. 이 중 그 어떤 것도 새로운 하드웨어를 필요로 하지 않습니다. 이 모든 것에는 더 많은 저녁 시간이 필요할 뿐입니다.
그리고 저작권에 대해 계속해서 솔직하게 말씀드리겠습니다. AI 에이전트가 C++와 Metal 셰이더 (shaders)를 작성했고, 메모리 장벽 (memory fences)과 페이지 정렬 (page alignment)을 통해 추론했으며, 제가 관광객이 거리 표지판을 읽듯 읽을 수밖에 없었던 코드에서 버그를 찾아냈습니다. 저는 질문과 방향, 고집, 그리고 — 알고 보니 — 10년 넘게 설정 파일 (config files)에 속아온 사람 특유의 디버깅 본능을 가져왔습니다. 우리 중 누구도 혼자서는 이것을 만들 수 없었을 것입니다. 이전에도 이런 조합을 누군가 만들어낸 적이 있는지는 확실하지 않지만, 초당 토큰 수 (tokens per second)보다 제가 주목할 가치가 있다고 생각하는 것은 바로 이 점입니다.
산은 이제 더 이상 진동만 하지 않습니다.
그것은 말을 합니다.
_S-MoE는 MIT 라이선스 하에 오픈 소스로 공개되어 있습니다. 코드, 철학, 그리고 실수들은 모두 공개되어 있습니다: github.com/melasistema/s-moe.
Luca Visciola와 (부디 C++와 저수준 프로그래밍 (low level programming)을 알기를 바라는) AI 에이전트가 함께 만들었습니다. 왜냐하면 저는 모르기 때문입니다 😅.
감사의 글: 지진 토모그래피 (seismic tomography) 개념은 SAR 기반 지하 영상화에 관한 출판된 연구인 Ing. Filippo Biondi의 작업을 철학적으로 번역한 것입니다. 첫 마디는 산의 것이며, 그 소리에 귀를 기울이는 직관은 그의 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기