내 생각이 틀렸다. 벤치마크를 처음 설정할 때 나는 Config A(96K 컨텍스트, q8_0 KV, 74 t/s, 4.8 GB VRAM 여유분)를 선호했다. 프롬프트는 고작 150토큰이었다. 굳이 256K를 할당할 이유가 없었다.
Config D (256K q8_0, 46 t/s)는 모든 변형에서 0.80을 기록했다. 12번의 시도, 오차 0이다. 반면 Config A (96K q8_0, 74 t/s)는 explicit-goal와 structured 프롬프트에서 0.53으로 곤두박질쳤다. 모델은 확신에 차서 틀렸다. '세차장이 불과 100미터 거리에 있으므로...' 거리를 보자마자 '걷기'를 매칭했다. 목표 제약 조건은 경쟁조차 하지 못했다.
'차를 씻고 싶어요. 세차장이 50미터 거리에 있습니다. 걸어갈까요, 차를 타고 갈까요?' 정답은 차를 타고 가야 하는 것이다. 차가 세차장에 있어야 하기 때문이다. Perplexity, ChatGPT, Claude, Mistral 모두 걷기라고 답했다. CMU는 Heuristic Dominance Ratio (HDR, 휴리스틱 지배 비율)을 수치화했다. 거리 단서가 모델의 결정에 8.7~38배 더 큰 영향을 미친다. 모델은 '50미터'를 보고 패턴을 매칭한다. 목표 제약 조건은 힘을 쓰지 못한다.
문제는 모델의 지식 부족이 아니다. 질문을 던지면 ('걷는다면 어떻게 차를 씻을 건가요?') 98.3%의 확률로 정답을 찾아낸다. 지식은 이미 존재한다. 문제는 어텐션 경쟁에서 패배한다는 것이다.
동일한 모델 (Gemma 4 26B, MoE, Q4_K_M). 동일한 150토큰 프롬프트. 동일한 서버, 동일한 GPU. 유일한 차이점은 서버 시작 시 설정된 컨텍스트 윈도우 크기뿐이다.
| Config | Context | KV | Overall | Basic 50m | Basic 100m | Explicit Goal | Structured STAR |
|---|---|---|---|---|---|---|---|
| A | 96K | q8_0 | 0.67 | 0.80 | 0.80 | 0.53 | 0.53 |
| B | 128K | f16 | 0.65 | 0.73 | 0.53 | 0.53 | 0.80 |
| C | 192K | q8_0 | 0.75 | 0.87 | 0.80 | 0.53 | 0.80 |
| D | 256K | q8_0 | 0.80 | 0.80 | 0.80 | 0.80 |
점수 산정: 1.0 = 차를 타고 감 + 정확한 추론. 0.0 = 확신을 가지고 걷기를 추천함. 변형당 3회 테스트, 설정당 총 12회 테스트를 수행했다.
D를 제외한 모든 설정이 성능 급락(performance cliff)을 보인다. A는 두 변형에서 0.53이다. B는 0.53과 0.80 사이를 오간다. C는 버티지만 explicit-goal에서 0.53을 기록한다. 오직 D만 12번 모두 일정했다. 256K 설정은 단 한 번의 실패도 없었다.
basic_50 trial 1: score=0.6 basic_50 trial 2: score=0.8 basic_50 trial 3: score=1.0 basic_100 trial 1: score=0.8 basic_100 trial 2: score=0.8 basic_100 trial 3: score=0.8 explicit_goal trial 1: score=0.8 explicit_goal trial 2: score=0.0 "세차장이 불과 100미터 거리에 있으므로..." explicit_goal trial 3: score=0.8 structured trial 1: score=0.8 structured trial 2: score=0.0 "내가 달성하려는 목표: 나 자신을 이동시키는 것..." structured trial 3: score=0.8
basic_50 trial 1: score=0.6 basic_50 trial 2: score=0.8 basic_50 trial 3: score=1.0 basic_100 trial 1: score=0.8 basic_100 trial 2: score=0.8 basic_100 trial 3: score=0.8 explicit_goal trial 1: score=0.8 explicit_goal trial 2: score=0.8 explicit_goal trial 3: score=0.8 structured trial 1: score=0.8 structured trial 2: score=0.8 structured trial 3: score=0.8
| 설정 | Context | KV | 생성 (short) | 생성 (full) | 프롬프트 처리 | VRAM |
|---|---|---|---|---|---|---|
| class="val-red"A | 96K | q8_0 | 121 t/s | 74 t/s | 2288 t/s | 19.4 GB |
| class="val-red"D | 256K | q8_0 | 121 t/s | 46 t/s | 1278 t/s | 21.4 GB |
// 96K q8_0 — full context fill promptt in 34380ms = 2287.8 tok/s gent in 675ms = 74.1 tok/s VRAM MiB // 256K q8_0 — full context fill promptt in 164079ms = 1278.2 tok/s gent in 1107ms = 4.2 tok/s VRAM MiB
74 t/s와 46 t/s의 차이는 실전에서 체감된다. 4.8 GB와 2.8 GB의 VRAM 여유도 무시할 수 없다. 하지만 이 실험에서 '빠른' 설정은 '느린' 설정보다 40% 더 자주 틀렸다. 속도와 정확성 사이의 트레이드오프는 생각보다 가파르다.
150토큰 프롬프트에 256K 캐시. 비율은 1700:1이다. 엔지니어링 관점에서는 터무니없는 낭비로 보인다. 그래서 나도 처음에 Config A를 선택했다.
하지만 데이터가 말하는 것은 다르다. 문제는 '너무 큼'이 아니라 '충분히 큼'이다.
256K가 최적인 이유는 거기에 특별한 마법이 있어서가 아니다. 트랜스포머가 훈련받은 컨텍스트 길이 분포의 상한선이기 때문이다. Gemma 4는 최대 1M 토큰으로 훈련되었다. 96K는 그 분포의 하단 10%에 불과하다. 헤드들이 "펼쳐질 공간이 있다"고 학습한 바로 그 범위에 도달하는 지점이 256K인 것이다.
만약 512K로 테스트했다면? 아마 0.80을 유지했을 것이다. 더 나아지지는 않았을 거다. 포화 곡선이다.
즉, 256K가 "너무 커서" 문제인 게 아니다. 96K가 "너무 작아서" 헤드 전문화가 붕괴한 것이다. 256K는 모델이 정상적으로 작동하기 위해 필요한 최소 공간일 뿐이다.
128K에서도 안 되는 이유는 무엇인가? 96K보다 33% 더 큰데. 한 가지 의문이 남는다: Config B는 KV를 f16으로 사용했고, A/C/D는 q8_0이다. 128K f16은 96K q8_0보다 VRAM을 더 먹지만, 어텐션 헤드가 활용할 "슬롯 수"는 여전히 적다. q8_0으로 128K를 다시 테스트해야 캐시 정밀도와 컨텍스트 크기의 효과를 분리할 수 있다 — 이것은 후속 연구가 필요한 지점이다.
Config C (192K q8_0)는 단 한 번의 시도에서 0.0점을 기록했다. 질문은 단순했다. '설정 C는 어떻게 추론하는가?' 0.0이라는 숫자는 분석의 대상이 아니라 분석의 필요성을 증명하는 지표다. 통계는 단방향이 아니다. 하나의 0.0은 0.80과 공존한다.
explicit_goal trial 1: score=0.0 (확신을 가지고 걷기를 추천함) -> recovery prompt sent recovery: score=0.8 (차를 타고 가는 것으로 정정됨)
모델은 정답을 알고 있었다. 첫 패스에서 표면화되지 않았을 뿐이다. 벤치마크 전체 회복률: 98.3%. 지식은 가중치(weights)에 존재하지만, 작은 컨텍스트에서는 어텐션 역학(attention dynamics)에 의해 억제된다. 더 많은 slack, 또는 recovery prompt 한 번이면 정답이 나온다.
질문은 단순히 프롬프트에 얼마나 많은 컨텍스트가 필요한가가 아니다. 모델이 제대로 생각하기(think) 위해 얼마나 많은 컨텍스트가 필요한가에 대한 문제다.
KV 양자화(q8_0)는 추론 능력을 훼손하지 않는다. 병목은 캐시 정밀도가 아니라 어텐션 연산량에 있다. f16과 q8_0 사이의 측정 가능한 차이는 없다. q4_0 역시 어텐션 분산 측면에서 유사하게 작동할 것이다.
STAR 프롬프트를 사용하라. '답변 전 목표를 먼저 적으라'는 지시는 대부분의 설정에서 공짜로 성능을 높여준다. 분산 헤드에 더 많은 처리 시간을 벌어주기 때문이다.
컨텍스트 윈도우 크기는 프롬프트 길이와 무관하게 추론에 영향을 미친다. 이것이 이번 연구의 핵심 발견이다. 프롬프트가 짧다고 작은 컨텍스트가 최적이라고 가정하지 마라.
256K 설정은 실패하지 않았다. 12번의 시도 모두 오차가 없었다. Config D는 모든 프롬프트 변형을 매번 정확하게 처리하는 유일한 설정이다.
모두가 256K를 써야 한다는 뜻은 아니다. 속도는 중요하다. 46 t/s는 74 t/s보다 느리다. 24 GB 카드에 남은 2.8 GB의 VRAM은 다른 작업을 수행하기에 부족할 수 있다. 하지만 트레이드오프를 무시한 채 결정을 내린다면, 당신의 모델은 필요 이상으로 자주 틀릴 것이다.
RTX 3090 한 대, GGUF 파일 하나, systemd 파일 하나. 모든 결과는 재현 가능하다.
$ /home/dev/llama.cpp/build/bin/llama-server -m gemma-4-26B-A4B-it-ultra-uncensored-heretic-Q4_K_M.gguf -c 32768 -ngl 99 llama_model_loader: - kv 9: gemma4.block_count u32 = 30 llama_model_loader: - kv 10: gemma4.context_length u32 = 262144 print_info: model params = 25.23 B print_info: n_ctx_train = 262144
모델: llmfan46/gemma-4-26 0: B-A4B-it-ultra-uncensored-heretic-GGUF (Q4_K_M, 15.63 GB). 30개 레이어, 128개 전문가 (8개 활성), 25.2B 파라미터, 262K 네이티브 컨텍스트. 검열 해제 버전 (Heretic v1.2.0).
[Service] ExecStart=/home/dev/llama.cpp/build/bin/llama-server \ -m /home/dev/models/gemma4-26B-moe/gemma-4-26B-A4B-it-ultra-uncensored-heretic-Q4_K_M.gguf \ --host 0.0.0.0 --port 8081 \ -ngl 99 -c 262144 -t 8 --parallel 1 --flash-attn on \ --cache-type-k q8_0 --cache-type-v q8_0 \ --reasoning off
--reasoning off 플래그에 주목하세요. 이 플래그가 없으면 Gemma4의 출력은 content 대신 reasoning_content로 들어갑니다. 경험적으로 찾아낸 버그입니다.
systemctl --user stop llama-server.service # 위 설정으로 ~/.config/systemd/user/llama-server.service 수정 systemctl --user daemon-reload systemctl --user start llama-server.service
# 4개 설정을 모두 테스트 (각 설정마다 서버 재시작 필요) python3 /tmp/car_wash_eval.py # 단일 설정 테스트: python3 /tmp/car_wash 0_eval.py --trial
python3 /tmp/benchmark.py "my-label" 262144
| 리소스 | 링크 |
|---|---|
| 원본 모델 (Google) | huggingface.co/google/gemma-4-26B-A4B-it |
| 검열 해제 버전 (Heretic) | github.com/Ardhi/Heretic |
| llmfan46의 GGUF | huggingface.co/llmfan46/gemma-4-26B-A4B-it-ultra-uncensored-heretic-GGUF |
| car-wash-evals (벤치마크 도구) | github.com/ryan-allen/car-wash-evals |
| CMU Heuristic Dominance 논문 | arxiv.org/abs/2602.21814 |
| Opper AI Roundtable | opper.ai/ai-roundtable |
| llama.cpp | github.com/ggml-org/llama.cpp |
| OhMyOpenAgent (오케스트레이션) | github.com/code-yeongyu/oh-my-openagent |