22
33![ quant.cpp Hero] ( docs/assets/hero.png )
44
5- 로컬 LLM을 위한 미니멀 C 추론 엔진. 33K LOC. 외부 라이브러리 없음.
5+ 로컬 LLM을 위한 미니멀 C 추론 엔진. [ ** quant.h** ] ( #단일-헤더-모드 ) 단일 헤더로도 제공됩니다.
6+
7+ 33K LOC. 외부 라이브러리 없음. 오후 한나절이면 전체 코드를 읽을 수 있습니다.
68
79[ ![ License] ( https://img.shields.io/badge/license-Apache%202.0-blue )] ( )
810[ ![ CI] ( https://img.shields.io/github/actions/workflow/status/quantumaikr/quant.cpp/ci.yml?label=CI )] ( )
911[ ![ Tests] ( https://img.shields.io/badge/tests-34%20pass-brightgreen )] ( )
1012
1113---
1214
13- ## 같은 하드웨어에서 4배 긴 컨텍스트
15+ ## 같은 하드웨어에서 ~ 4배 긴 컨텍스트
16+
17+ KV 캐시 압축으로 토큰당 메모리를 3.8배 줄여, 컨텍스트를 그만큼 확장합니다.
1418
15- Delta KV 압축으로 품질 손실 없이 4배 더 많은 컨텍스트를 처리합니다.
19+ | 하드웨어 | 모델 | FP16 KV | 4-bit K + Q4 V | 배율 |
20+ | ----------| ------| ---------| ----------------| ------|
21+ | 8GB 노트북 | Llama 8B (Q4) | ~ 16K 토큰 | ~ 61K 토큰 | 3.8x |
22+ | 16GB Mac Air | SmolLM2 1.7B | ~ 78K 토큰 | ~ 298K 토큰 | 3.8x |
23+ | 24GB RTX 3090 | Llama 8B (Q4) | ~ 147K 토큰 | ~ 559K 토큰 | 3.8x |
1624
17- | 하드웨어 | 모델 | Before | After | 배율 |
18- | ----------| ------| --------| -------| ------|
19- | 8GB 노트북 | Llama 8B (Q4) | 16K 토큰 | 61K 토큰 | 3.8x |
20- | 16GB Mac Air | SmolLM2 1.7B | 78K 토큰 | 298K 토큰 | 3.8x |
21- | 24GB RTX 3090 | Llama 8B (Q4) | 147K 토큰 | 559K 토큰 | 3.8x |
25+ * KV 메모리 절감 기반 추정치. 실제 컨텍스트는 모델 가중치 이후 가용 메모리에 따라 다릅니다.*
2226
2327``` bash
24- ./quant model.gguf -p " hello" -k uniform_4b -v q4
28+ ./quant model.gguf -p " hello"
2529```
2630
2731---
@@ -30,16 +34,76 @@ Delta KV 압축으로 품질 손실 없이 4배 더 많은 컨텍스트를 처
3034
3135| | quant.cpp | llama.cpp |
3236| --| -----------| -----------|
33- | 코드베이스 | 33K LOC, Pure C | 250K+ LOC, C++ |
34- | KV 압축 품질 | PPL -3.2% (FP32보다 좋음) | PPL +10.6% |
35- | 의존성 | zero (libc/libm only) | - |
36- | 설계 목표 | 읽고, 이해하고, 수정 가능 | 기능 완성도 |
37+ | 코드 | ** 33K LOC** , Pure C | 250K+ LOC, C++ |
38+ | 설계 | 읽고, 수정하고, 임베딩 | 기능 완성도 |
39+ | 의존성 | libc + pthreads only | ggml 프레임워크 |
40+ | KV 압축 | 4-bit: PPL ** +0.0%** , 3-bit: +1.3% | PPL +10.6% |
41+
42+ quant.cpp는 포크가 아닙니다. 처음부터 새로 만든 독립 엔진입니다. 목표: ** 이해하고, 커스터마이즈하고, 내 제품에 넣을 수 있는 LLM 추론.**
3743
38- 같은 모델 (SmolLM2 1.7B), 같은 벤치마크. llama.cpp의 Q4_0 KV는 품질을 떨어뜨립니다. quant.cpp는 오히려 개선합니다.
44+ - ** Read** — 33K줄. 전체 forward pass가 하나의 파일에 들어갑니다.
45+ - ** Modify** — Pure C11, 모듈러. 양자화 타입 추가, 어텐션 커널 교체, 샘플링 전략 변경.
46+ - ** Embed** — 프레임워크 없음, 패키지 매니저 없음. 소스를 복사하면 어디서든 컴파일.
3947
4048---
4149
42- ## 빠른 시작
50+ ## 단일 헤더 모드
51+
52+ 파일 1개 복사. 어떤 C 프로젝트에든 LLM 추가.
53+
54+ ``` c
55+ #define QUANT_IMPLEMENTATION
56+ #include " quant.h"
57+ #include < stdio.h>
58+
59+ static void on_token (const char* text, void* ud) {
60+ (void)ud;
61+ printf("%s", text);
62+ fflush(stdout);
63+ }
64+
65+ int main() {
66+ quant_model* m = quant_load("model.gguf");
67+ quant_ctx* c = quant_new(m, NULL);
68+ quant_generate(c, "Hello!", on_token, NULL);
69+ quant_free_ctx(c);
70+ quant_free_model(m);
71+ }
72+ ```
73+
74+ ```bash
75+ cc app.c -o app -lm -lpthread # 끝
76+ ```
77+
78+ 15K줄, 628KB. cmake 없음, 빌드 시스템 없음, 프레임워크 없음.
79+
80+ ** 전체 API** (6개 함수):
81+
82+ | 함수 | 설명 |
83+ | ------| ------|
84+ | ` quant_load(path) ` | GGUF 모델 파일 로드 |
85+ | ` quant_new(model, config) ` | 추론 컨텍스트 생성 (config=NULL이면 기본값) |
86+ | ` quant_generate(ctx, prompt, callback, userdata) ` | 콜백으로 토큰 스트리밍 |
87+ | ` quant_ask(ctx, prompt) ` | 전체 응답 문자열 반환 (호출자가 free) |
88+ | ` quant_free_ctx(ctx) ` | 컨텍스트 해제 |
89+ | ` quant_free_model(model) ` | 모델 해제 |
90+
91+ ** 설정 옵션:**
92+
93+ ``` c
94+ quant_config cfg = {
95+ .temperature = 0.7f, // 샘플링 온도
96+ .top_p = 0.9f, // nucleus 샘플링
97+ .max_tokens = 256, // 최대 생성 토큰 수
98+ .n_threads = 4, // matmul 스레드 수
99+ .kv_compress = 1, // 0=끔, 1=4-bit K+V, 2=delta+3-bit
100+ };
101+ quant_ctx* c = quant_new(model, &cfg);
102+ ```
103+
104+ ---
105+
106+ ## 빠른 시작 (Full Build)
43107
44108``` bash
45109git clone https://github.com/quantumaikr/quant.cpp && cd quant.cpp
@@ -49,14 +113,20 @@ cmake --build build -j$(nproc)
49113# 추론 실행
50114./build/quant model.gguf -p " hello"
51115
52- # KV 압축 (4-bit K + Q4 V, 3.8x)
116+ # KV 압축 (4-bit K + Q4 V, 3.8x, 추천 )
53117./build/quant model.gguf -p " hello" -k uniform_4b -v q4
54118
55- # Delta 압축 (3-bit K + Q4 V, 4.3x)
119+ # Delta 압축 (3-bit K + Q4 V, 4.3x, 최대 압축 )
56120./build/quant model.gguf -p " hello" -k uniform_3b -v q4 --delta
57121
58122# PPL 측정
59123./build/quant model.gguf --ppl input.txt -k uniform_4b -v q4
124+
125+ # JSON 출력 (CI 연동용)
126+ ./build/quant model.gguf --ppl input.txt -k uniform_4b --json
127+
128+ # 버전 확인
129+ ./build/quant --version
60130```
61131
62132---
@@ -65,70 +135,96 @@ cmake --build build -j$(nproc)
65135
66136### 압축 모드
67137
68- | 구성 | 압축률 | PPL vs FP32 | 용도 |
69- | ------| --------| -------------| ------|
70- | delta + 3b K + Q4 V | ~ 4.3x | -3.2% | 최대 압축 |
71- | delta + 4b K + Q4 V | ~ 3.8x | -12.2 % | 최고 품질 |
72- | uniform 4b K + Q4 V | 3.8x | -7.8 % | 심플, delta 오버헤드 없음 |
138+ | 구성 | 압축률 | PPL vs FP32 (WikiText-2) | 용도 |
139+ | ------| --------| -------------------------- | ------|
140+ | delta + 3b K + Q4 V | ~ 4.3x | ** +1.3% ** | 최대 컨텍스트 |
141+ | delta + 4b K + Q4 V | ~ 3.8x | ~ 0 % | 최고 품질 |
142+ | uniform 4b K + Q4 V | 3.8x | -0.4 % | 심플, delta 오버헤드 없음 |
73143| uniform 4b K + FP16 V | 1.6x | +0.0% | 무손실 |
74144
75145### Delta 압축 원리
76146
77- 표준 KV 캐시는 각 key를 그대로 저장합니다. Delta 압축은 인접 key의 * 차이* 를 저장합니다 — 비디오의 P-frame과 I-frame처럼.
78-
79- 트랜스포머의 인접 key는 절대값 범위의 ~ 30%만 차이납니다. 이 작은 범위 덕분에 3-bit 양자화로 충분합니다. Delta 없이 3-bit는 PPL +62%. Delta와 함께라면 PPL -3.2%.
147+ 표준 KV 캐시는 각 key를 그대로 저장합니다. Delta 모드는 ` key[t] - reconstruct(key[t-1]) ` 을 저장합니다 — 비디오 P-frame처럼.
80148
81- 64 토큰마다 FP32 I-frame을 저장하여 누적 드리프트를 방지합니다 .
149+ 트랜스포머의 인접 key는 절대값 범위의 ~ 30%만 차이납니다. 이 작은 범위 덕분에 3-bit 양자화가 가능합니다. Delta 없이 3-bit는 PPL +62%. Delta와 함께라면 ** +1.3% ** .
82150
83- ### 전체 PPL 결과 (SmolLM2 1.7B, 999 토큰)
151+ 64 토큰마다 FP32 I-frame을 저장하여 드리프트를 방지합니다.
84152
85- | 구성 | PPL | vs FP32 | 비고 |
86- | ------| -----| ---------| ------|
87- | FP32 baseline | 14.58 | -- | 기준 |
88- | delta + 4b K + Q4 V | 12.80 | -12.2% | 최고 품질 |
89- | delta + 3b K + Q4 V | 14.11 | -3.2% | 최고 압축 |
90- | uniform 4b K + Q4 V | 13.44 | -7.8% | 검증됨 |
91- | uniform 3b K + Q4 V (no delta) | 23.62 | +62% | delta 필수 |
153+ ### WikiText-2 PPL (SmolLM2 1.7B, 표준 벤치마크)
92154
93- ### 모델별 검증 (4b K + Q4 V)
155+ | 구성 | PPL | vs FP32 |
156+ | ------| -----| ---------|
157+ | FP32 baseline | 14.63 | -- |
158+ | uniform 4b K + FP16 V | 14.63 | ** +0.00%** |
159+ | uniform 4b K + Q4 V | 14.57 | -0.4% |
160+ | delta + 3b K + Q4 V | 14.82 | +1.3% |
161+ | uniform 3b (no delta) | — | +62% |
94162
95- | 모델 | PPL 변화 |
96- | ------| ----------|
97- | SmolLM2 1.7B | -1.6% |
98- | Qwen3.5 0.8B | +0.9% |
99- | Qwen3.5 4B | +0.6% |
163+ 모델별 검증 (4b K + Q4 V): SmolLM2 1.7B (-1.6%), Qwen3.5 0.8B (+0.9%), Qwen3.5 4B (+0.6%).
100164
101165---
102166
103167## 지원 모델
104168
105- | 모델 | 아키텍처 | 파라미터 | KV 검증 |
106- | ------| ----------| ----------| --------- |
107- | SmolLM2-1.7B | Llama | 1.7B | PPL -1.6% |
108- | Qwen3.5-0.8B | Qwen3.5 (DeltaNet) | 752M | PPL +0.9% |
109- | Qwen3.5-4B | Qwen3.5 (DeltaNet) | 4B | PPL +0.6% |
110- | Qwen3.5-35B-A3B | Qwen2-MoE | 35B (3B active) | 4-bit K verified |
111- | Gemma 3 270M | Gemma 3 | 270M | 4-bit K verified |
112- | Gemma 4 E2B | Gemma 4 | 2B | WIP |
169+ | 모델 | 아키텍처 | 파라미터 | 상태 |
170+ | ------| ----------| ----------| ------|
171+ | SmolLM2-1.7B | Llama | 1.7B | PPL 검증 |
172+ | Qwen3.5-0.8B | Qwen3.5 (DeltaNet) | 752M | PPL 검증 |
173+ | Qwen3.5-4B | Qwen3.5 (DeltaNet) | 4B | PPL 검증 |
174+ | Qwen3.5-35B-A3B | Qwen2-MoE | 35B (3B active) | 동작 |
175+ | Gemma 3 270M | Gemma 3 | 270M | 동작 |
176+ | Gemma 4 E2B | Gemma 4 | 2B | 실험적 (비표준 GGUF) |
113177
114178아키텍처: Llama/Qwen3.5 (공유 경로), Gemma 3/4 (sliding + full attention), Qwen2-MoE.
115179
180+ GGUF 포맷. llama.cpp 호환 모델 파일을 그대로 사용합니다.
181+
116182---
117183
118- ## FAQ
184+ ## 백엔드
119185
120- ** Delta 압축은 어떻게 작동하나요?**
186+ | 백엔드 | 플랫폼 | 상태 |
187+ | --------| --------| ------|
188+ | NEON | ARM CPU | Production |
189+ | AVX2 | x86 CPU | Production |
190+ | Metal | Apple Silicon | Verified |
191+ | CUDA | NVIDIA GPU | Compiles |
192+ | Vulkan | Cross-platform | Compiles |
121193
122- 각 key를 직접 저장하는 대신 ` key[t] - reconstruct(key[t-1]) ` 을 저장합니다. 트랜스포머의 인접 key는 높은 상관관계를 가지므로 delta의 범위가 절대값의 ~ 30%입니다. 64 토큰마다 full-precision I-frame으로 드리프트를 방지합니다.
194+ ---
195+
196+ ## FAQ
123197
124198** llama.cpp와 뭐가 다른가요?**
125199
126- quant.cpp는 독립 추론 엔진입니다 (33K LOC, Pure C) — 포크나 래퍼가 아닙니다. KV 압축에서 핵심 차이: llama.cpp Q4_0은 SmolLM2 1.7B에서 PPL +10.6%. quant.cpp의 4-bit K는 같은 모델에서 PPL +0.0%.
200+ llama.cpp는 전체 기능을 갖춘 추론 프레임워크 (250K+ LOC). quant.cpp는 읽고, 수정하고, 내 프로젝트에 넣을 수 있는 미니멀 엔진 (33K LOC). KV 압축 차이: llama.cpp Q4_0은 SmolLM2 1.7B에서 PPL +10.6%. quant.cpp 4-bit K는 PPL +0.0%.
201+
202+ ** 내 앱에 임베딩할 수 있나요?**
203+
204+ 네. 두 가지 방법:
205+ 1 . ** 단일 헤더** (가장 간편): ` quant.h ` 를 프로젝트에 복사. ` .c ` 파일 하나에 ` #define QUANT_IMPLEMENTATION ` . 끝.
206+ 2 . ** 전체 라이브러리** : ` libturboquant.a ` 에 링크하고 ` tq_load_model() ` / ` tq_generate() ` 호출.
207+
208+ Linux, macOS, Windows, iOS, Android, WASM에서 동작합니다.
209+
210+ ** quant.h와 Full Build의 차이는?**
211+
212+ ` quant.h ` 는 핵심 추론 엔진 (15K LOC)을 단일 파일에 담은 것. Full Build (33K LOC)에는 GPU 백엔드 (Metal, CUDA, Vulkan), MoE 라우팅, 고급 양자화 타입, CLI 도구, 벤치마크가 추가됩니다. 임베딩에는 quant.h, 연구/개발에는 Full Build.
127213
128214** 3-bit 이하는요?**
129215
130- 광범위하게 테스트했습니다: 2-bit delta, sub-block scaling, multi-hash, error feedback, NF2, online SVD 등. 어떤 접근도 허용 가능한 품질을 달성하지 못했습니다. 근본 장벽: step당 코사인 유사도 0.997이 200 step 후 0.885로 누적됩니다. 3-bit + delta가 실용적 최소입니다.
216+ 광범위하게 테스트했습니다: 2-bit delta, sub-block scaling, multi-hash, error feedback, NF2, online SVD. 어떤 접근도 허용 가능한 품질을 달성하지 못했습니다. 근본 장벽: step당 코사인 0.997이 200 step 후 0.885로 누적. 3-bit + delta가 실용적 최소.
217+
218+ ---
219+
220+ ## 참고 논문
221+
222+ - [ TurboQuant] ( https://arxiv.org/abs/2504.19874 ) (ICLR 2026) — KV 캐시 압축 이론
223+ - [ QJL] ( https://arxiv.org/abs/2406.03482 ) (AAAI 2025) — 양자화 JL 변환
224+ - [ PolarQuant] ( https://arxiv.org/abs/2502.02617 ) (AISTATS 2026) — 극좌표 양자화
131225
132226---
133227
134228** [ QuantumAI] ( https://quantumai.kr ) ** | [ GitHub] ( https://github.com/quantumaikr/quant.cpp )
229+
230+ [ ![ Star History Chart] ( https://api.star-history.com/svg?repos=quantumaikr/quant.cpp&type=Date )] ( https://star-history.com/#quantumaikr/quant.cpp&Date )
0 commit comments