이 레포가 무엇을 하는 물건인가.
ds4(DwarfStar)는 DeepSeek V4 Flash/PRO 전용 로컬 추론 엔진이다. llama.cpp처럼 수백 가지 모델을 돌릴 수는 없지만, 이 특정 MoE 아키텍처의 KV 캐시 구조·양자화 레이아웃·라우팅 패턴을 손으로 최적화했기 때문에 동급 하드웨어에서 더 빠른 토큰/초를 낸다.
Redis의 창시자 antirez가 주도한다는 점이 특이하다. 시스템 프로그래밍 철학("작고, 읽기 쉽고, 빠르게")이 그대로 이 코드베이스에 녹아 있다.
트렌딩 이유, 경쟁 제품 대비 장점.
ds4가 주목받는 첫 번째 이유는 antirez라는 이름이다. Redis를 C로 직접 만들어 수백만 서버에 배포된 인물이 LLM 추론 엔진을 밑바닥부터 쌓겠다고 선언하면, 커뮤니티는 주목할 수밖에 없다. 두 번째는 DeepSeek V4의 타이밍이다. 284B(Flash)~1.6T(PRO) 파라미터지만 MoE 구조 덕분에 실제 활성 파라미터는 13B~49B로 줄어, MacBook Pro M3 Max 128GB 같은 고사양 개인 장비에서 실행 가능한 첫 번째 준(準)-프론티어급 모델이 되었다. ds4는 이 기회를 노렸다.
llama.cpp는 수백 개 모델을 지원하는 범용 런타임이다. ds4는 DeepSeek V4 Flash/PRO 전용이다. "llama.cpp보다 낫다"는 비교 자체가 틀렸다 — 목적이 다르다. ds4는 이 한 모델을 완벽하게 돌리겠다는 좁은 베팅이다. 내일 더 좋은 오픈 모델이 나오면 ds4는 대상 모델을 교체할 수도 있다고 README에서 솔직하게 밝힌다.
ds4는 DeepSeek 공식 구현에서 얻은 로짓 벡터와 자체 출력을 비교하는 회귀 테스트를 유지한다. "빠르지만 틀린" 구현이 아니라, 정확성을 먼저 증명하고 속도를 더하는 설계 철학을 고수한다.
모델이 RAM에 다 들어오지 않아도 SSD에서 스트리밍으로 전문가(Expert) 가중치를 로드하는 기능을 Metal에서 지원한다. MacBook 64GB에서도 96GB 모델을 (느리지만) 구동할 수 있다. 메모리를 "있다/없다"의 이분법이 아니라 속도 스펙트럼으로 보는 관점 전환이다.
두 대의 MacBook을 Thunderbolt 5 케이블로 연결해 모델 레이어를 분할, 단일 머신에는 올릴 수 없는 전체 PRO Q4(약 2TB급) 모델을 두 대의 Mac Studio(각 512GB)로 운용하는 것도 지원한다. 프리필(prefill)에서는 파이프라인 병렬성으로 최대 1.85배 속도 향상도 측정됐다.
C 코어 / GPU 백엔드 3종 / 빌드 / 모델 포맷 상세.
| 레이어 | 기술 | 역할 | 파일 |
|---|---|---|---|
| 코어 엔진 | C99 | GGUF 로딩, 토크나이저, KV 캐시, 샘플링, 세션 관리 | ds4.c (27k줄), ds4.h |
| Metal 백엔드 | Objective-C + Metal MSL | macOS Apple Silicon GPU 커널 실행, no-copy MTLBuffer mmap | ds4_metal.m (26k줄), metal/*.metal (20개) |
| CUDA 백엔드 | CUDA C++ | NVIDIA GPU 커널, DGX Spark / GB10 전용 최적화 | ds4_cuda.cu (13k줄) |
| ROCm 백엔드 | HIP / ROCm | AMD Strix Halo(gfx1151) GPU, rocWMMA 행렬 연산 | ds4_rocm.cu, rocm/*.cuh (23개) |
| HTTP 서버 | C (내장 HTTP) | OpenAI/Anthropic 호환 REST API, 스트리밍 SSE | ds4_server.c (15k줄) |
| CLI / REPL | C + linenoise | 대화형 터미널 인터페이스, /read /think 명령 | ds4_cli.c, linenoise.c |
| 코딩 에이전트 | C | 내장 코딩 에이전트, API 경계 없이 세션 직접 접근 | ds4_agent.c (10k줄) |
| KV 저장소 | C + rax(기수트리) | 서버 KV 캐시 디스크 체크포인트, 세션 복원 | ds4_kvstore.c, rax.c |
| SSD 스트리밍 | C | VRAM 부족 시 GGUF에서 Expert 가중치 온디맨드 로드 | ds4_ssd.c |
| 분산 추론 | C + TCP | 레이어 분할 멀티머신 추론, HELLO/WORK 프레임 프로토콜 | ds4_distributed.c (8k줄) |
| GGUF 도구 | C + Python | 양자화, imatrix 생성, 품질 비교, mixed expert 스플라이싱 | gguf-tools/ 하위 |
| 벤치마크 | C | 컨텍스트 프론티어별 prefill/generation t/s 측정, CSV 출력 | ds4_bench.c |
| 모델 포맷 | GGUF (전용 레이아웃) | antirez 제공 HF 저장소의 전용 텐서 레이아웃만 허용 | huggingface.co/antirez/deepseek-v4-gguf |
| 빌드 | GNU Make | macOS/Linux 크로스 타겟 빌드 (Metal/CUDA/ROCm/CPU) | Makefile |
| 방향성 조종 | C + 벡터 파일 | 활성화 공간에 벡터를 더해 모델 출력 성향을 유도 | dir-steering/ |
ds4 = 전용 사출 금형이고, DeepSeek V4 Flash는 그 금형으로만 찍어내는 제품이다. 범용 3D 프린터(llama.cpp)는 무엇이든 만들 수 있지만 느리다. 전용 금형은 하나만 만들 수 있지만 속도와 완성도가 다르다.
ASCII 시스템 구조도 + 핵심 설계 패턴.
ds4.c의 엔진 코드는 GGUF 파일 전체를 RAM으로 복사하지 않는다. 대신 mmap()으로 파일을 주소 공간에 매핑한다. Metal 백엔드에서는 이 mmap 포인터를 MTLBuffer로 직접 래핑(no-copy)해 GPU에 바로 전달한다. 결과적으로 80GB 모델을 로드해도 실제 RAM 복사가 발생하지 않고, 페이지 캐시가 알아서 필요한 부분만 로드한다.
DeepSeek V4의 독특한 KV 캐시 설계를 ds4가 완벽하게 구현한다. 표준 트랜스포머는 모든 토큰의 KV를 저장해 컨텍스트 길이에 비례해 메모리가 폭발한다. DeepSeek V4는 시간 축 압축을 사용한다.
MoE 모델의 특성상 전체 가중치 중 "라우팅된 전문가"가 대용량을 차지한다. ds4의 SSD 스트리밍은 이 전문가 가중치를 GGUF에서 온디맨드로 읽되, 공유 전문가 계산 시간을 활용해 다음 라우팅 전문가를 미리 로드(prefetch)한다. 캐시 미스 페널티를 숨기는 전형적인 레이턴시 히딩 기법이다.
파일 하나하나가 어떤 역할을 하는지.
ds4.c는 엔진 블록이다. 여기서 GGUF 파일을 읽고, 토크나이저를 초기화하고, Metal/CUDA/ROCm에 GPU 작업을 위임한다. ds4_server.c는 서비스 창구이고 ds4_cli.c는 정비사 핸들이다. 커널(metal/*.metal, rocm/*.cuh)은 실제로 GPU 위에서 돌아가는 어셈블리급 최적화 코드다.
저수준 추론 / GPU 커널 / C 시스템 프로그래밍 배울 것.
ds4.c는 C99 표준 코드다. mmap()·mlock()·pthread·posix_memalign()같은 POSIX API를 실전에서 어떻게 쓰는지 볼 수 있다. antirez의 코딩 스타일—작은 함수, 명확한 변수명, 과도한 추상화 거부—을 직접 체감할 수 있는 희귀한 코드베이스다.
GGUF는 llama.cpp에서 표준화한 LLM 가중치 파일 포맷이다. ds4는 직접 GGUF 파서를 구현한다. 헤더·메타데이터·텐서 디렉토리를 어떻게 읽는지, 텐서 타입(IQ2XXS·Q2_K·Q4_K·FP8 등)별 블록 구조가 어떻게 다른지 소스 코드로 배울 수 있다.
metal/ 폴더의 .metal 파일은 GLSL과 유사한 Metal Shading Language(MSL)로 작성된 GPU 커널이다. 행렬 곱(dense.metal), 어텐션(flash_attn.metal), MoE 라우팅(moe.metal)이 실제로 어떻게 threadgroup/simdgroup을 사용하는지 볼 수 있다.
DeepSeek V4는 Mixture of Experts(MoE) 모델이다. 입력마다 소수의 "전문가"만 활성화된다. ds4 코드에서 라우터가 어떻게 top-K 전문가를 선택하고, 활성화된 전문가 가중치만 연산하는지 C와 Metal 코드 레벨에서 추적할 수 있다.
LLM에서 가장 비싼 메모리가 KV 캐시다. ds4는 세션 간 KV 재사용, 디스크 체크포인트(snapshot), 접두사 매칭 최적화를 직접 구현한다. 컨텍스트가 길어질수록 어떻게 메모리를 관리하는지 실 코드로 배울 수 있다.
ds4.c의 GGUF 로딩 부분(1857~2100 라인 근처)을 읽고, 간단한 Python 스크립트로 동일한 GGUF 메타데이터를 파싱해 ds4 출력과 비교해 보자.
metal/norm.metal(RMSNorm)을 읽고 동일한 연산을 CPU Python NumPy로 구현해 봄으로써 GPU 커널과 레퍼런스 구현의 관계를 이해해 보자.
GPU / OS 요구사항 표 + 빌드 명령.
| 백엔드 | OS | 하드웨어 | 최소 RAM | 권장 모델 |
|---|---|---|---|---|
| Metal | macOS | Apple Silicon M2~M5 (M3 Max 이상 권장) | 96GB+ | q2-imatrix (Flash) |
| Metal (SSD 스트리밍) | macOS | Apple Silicon | 64GB | q2-imatrix (느림) |
| Metal (PRO 모델) | macOS | Mac Studio M3 Ultra | 512GB | pro-q2-imatrix |
| CUDA | Linux | NVIDIA DGX Spark / GB10 / 기타 CUDA GPU | 128GB | q2-imatrix |
| ROCm | Ubuntu 26.04 | AMD Strix Halo (gfx1151, Framework Desktop 등) | 128GB | q2-imatrix |
| CPU (진단용) | Linux (macOS 비권장) | 모든 CPU | RAM = 모델 크기 | 테스트용 only |
README가 명시한다: 현재 macOS 버전에는 가상 메모리 구현 버그가 있어 CPU 모드로 대형 모델을 추론하면 커널이 패닉을 일으켜 재부팅이 필요하다. macOS에서는 반드시 Metal 빌드를 사용해야 한다.
# macOS (Metal 백엔드)
make
# Linux CUDA (DGX Spark / GB10)
make cuda-spark
# Linux CUDA (기타 CUDA GPU)
make cuda-generic
# AMD Strix Halo (ROCm)
make strix-halo
# CPU만 (디버그/진단용)
make cpu
# 96/128GB RAM 권장 (imatrix 최적화 2비트)
./download_model.sh q2-imatrix
# 96/128GB RAM, 마지막 6레이어 Q4 혼합
./download_model.sh q2-q4-imatrix
# 256GB+ RAM (4비트, 고품질)
./download_model.sh q4-imatrix
# 512GB RAM (PRO 모델 2비트)
./download_model.sh pro-q2-imatrix
# 기본 CLI 대화
./ds4 -m ./ds4flash.gguf
# SSD 스트리밍 (64GB MacBook)
./ds4 -m ./ds4flash.gguf --ssd-streaming --ctx 32768 --nothink
# HTTP 서버 (OpenAI 호환 API)
./ds4-server -m ./ds4flash.gguf --ctx 100000
# 코딩 에이전트
./ds4-agent --chdir /path/to/ds4
# GPU 발열/팬 소음 제어 (70% 사용)
./ds4 --power 70
난이도별 3~5개 과제.
download_model.sh를 열고 curl을 이용한 HuggingFace 다운로드, 재개(resume) 로직, 심볼릭 링크 생성 방식을 분석해 보자. Bash 스크립트 실력을 키우는 좋은 출발점이다.
모델이 있는 환경이라면 ds4-bench를 다양한 컨텍스트 크기로 실행해 CSV를 생성한 후, Python의 pandas/matplotlib으로 시각화해 보자. "컨텍스트 길이 vs. prefill 속도" 그래프를 그려보는 것이 목표다.
ds4.c의 GGUF 파싱 코드를 참고해 Python으로 GGUF 파일을 열고 메타데이터(어휘 크기, 레이어 수, 어텐션 헤드 수 등)를 출력하는 스크립트를 짜보자. 바이너리 파일 파싱과 llama.cpp 생태계 이해가 목표다.
metal/norm.metal을 열고 RMSNorm의 epsilon 값을 1e-6에서 1e-5, 1e-4로 바꿔 가며 빌드·실행해 보자. 수치 안정성이 모델 출력에 미치는 영향을 직접 체감할 수 있다. GPU 커널 수정 → 재빌드 → 동작 확인의 사이클을 몸에 익히는 것이 목표다.
Mac이 두 대 있다면 Thunderbolt나 이더넷으로 연결하고 coordinator/worker로 나눠 분산 추론을 설정해 보자. 레이어 분할 전략(0:N vs N:output)에 따른 prefill/generation 속도 변화를 측정하고, ds4_distributed.c의 HELLO/WORK/RESULT 프로토콜 흐름을 코드에서 추적해 보자.
주차별 학습 경로.
| 주차 | 주제 | 학습 내용 | 실습 |
|---|---|---|---|
| 1주차 | C 언어 기초 | 포인터, 구조체, malloc/free, 파일 I/O, Makefile | 간단한 GGUF 메타데이터 파서 Python으로 작성 |
| 2주차 | Transformer 구조 | Self-Attention, MLP, RMSNorm, RoPE 위치 인코딩 수식 이해 | PyTorch로 최소 GPT-2 포워드 패스 구현 |
| 3주차 | MoE 아키텍처 | 라우터, Top-K Expert 선택, 부하 균형, SwiGLU 활성화 | SwitchTransformer 논문 읽고 간단한 MoE 구현 |
| 4주차 | 양자화 기초 | INT8/INT4 양자화, 블록 양자화(Q4_K, IQ2_XXS), calibration | llama.cpp의 quantize 소스 코드 읽기 |
| 5주차 | KV 캐시 설계 | KV 재사용, sliding window, prefix caching, GQA | ds4.c KV 캐시 코드 추적, 세션 복원 실험 |
| 6주차 | Metal / CUDA 기초 | GPU 스레드 계층(threadgroup/warp), 공유 메모리, atomic 연산 | 간단한 벡터 덧셈 Metal 커널 직접 작성 |
| 7주차 | Attention 커널 최적화 | Flash Attention 알고리즘, tiled matmul, softmax 수치 안정성 | flash_attn.metal 코드 분석 + FlashAttention 논문 읽기 |
| 8주차 | 시스템 최적화 | mmap, mlock, prefetch, 레이턴시 히딩, 분산 통신 | ds4_distributed.c WORK 프레임 처리 흐름 추적 |
이 레포를 읽으며 만나는 용어 정리.
| 키워드 | 한글 설명 |
|---|---|
| GGUF | llama.cpp 생태계의 표준 LLM 가중치 파일 포맷. 헤더/메타데이터/텐서를 하나의 파일에 담는다. |
| MoE (Mixture of Experts) | 입력마다 전체 전문가(FFN 층) 중 소수만 활성화하는 구조. 전체 파라미터 수는 많지만 실제 연산은 적다. |
| IQ2XXS / Q2_K | 2비트 양자화 포맷. 전문가(MoE Expert) 가중치에만 적용해 크기를 극단적으로 줄인다. ds4 기본 권장 포맷. |
| imatrix (Importance Matrix) | 양자화 시 중요한 가중치를 더 정밀하게 보존하도록 돕는 교정 행렬. imatrix 버전이 품질이 높다. |
| mmap | 파일을 메모리 주소 공간에 매핑하는 POSIX 시스템 콜. 복사 없이 파일을 RAM처럼 읽을 수 있다. |
| MTLBuffer | Metal(Apple GPU 프레임워크)의 GPU 메모리 버퍼. ds4는 mmap 포인터를 no-copy로 MTLBuffer로 래핑한다. |
| prefill / generation | LLM 추론 두 단계. prefill은 전체 프롬프트를 한 번에 처리(병렬), generation은 토큰을 하나씩 생성(순차). |
| KV 캐시 | Attention 계산 시 이전 토큰의 Key/Value를 저장해 재계산을 피하는 캐시. 컨텍스트 길이에 비례해 커진다. |
| SSD 스트리밍 | 모델이 RAM에 다 올라오지 않을 때, SSD에서 필요한 전문가 가중치를 온디맨드로 읽는 방식. |
| RoPE (Rotary Position Embedding) | 어텐션에서 토큰 위치를 인코딩하는 방식. 회전 행렬로 상대적 위치 관계를 표현한다. |
| RMSNorm | 레이어 정규화의 경량 버전. 평균 없이 제곱 평균만 사용해 연산이 빠르다. |
| SwiGLU | Swish 함수와 GLU(Gated Linear Unit)를 결합한 활성화 함수. 현대 LLM FFN의 표준. |
| Flash Attention | 어텐션을 타일 단위로 나눠 GPU 고대역폭 메모리(HBM) 접근을 최소화하는 알고리즘. O(N²) 메모리를 피한다. |
| CSA / HCA | DeepSeek V4의 Compressed Sparse Attention / Heavily Compressed Attention. 시간 축 압축으로 1M 컨텍스트를 가능하게 한다. |
| mHC (Manifold-Constrained Hyper-Connections) | 레이어 간 신호 전파 안정성을 높이는 DeepSeek V4 고유 구조. ds4_metal.m에서 dsv4_hc.metal로 구현된다. |
| 분산 추론 (Distributed Inference) | 여러 머신에 모델 레이어를 나눠 함께 추론하는 방식. 단일 머신에 올라오지 않는 대형 모델을 위한 해법. |
| directional steering | 모델 내부 활성화 벡터에 방향을 더해 출력 성향을 유도하는 기법. ds4는 이를 실험적으로 지원한다. |
| DwarfStar | ds4의 공식 프로젝트명. README 첫 줄에 등장. 파일명/바이너리명은 ds4로 통일. |
| linenoise | antirez가 직접 만든 경량 읽기 편한 터미널 라인 입력 라이브러리. Redis에도 쓰인다. |
| rax | antirez가 직접 만든 기수 트리(Radix Tree) 구현. ds4_kvstore의 키 색인으로 사용된다. |
출처 · 더 읽을 거리.