본문으로 건너뛰기

© 2026 Molayo

Qiita헤드라인2026. 06. 05. 09:26

【#8】ds4.c 해독하기

요약

DeepSeek V4 전용 추론 엔진인 DwarfStar(ds4)의 핵심 기술을 분석합니다. 파인튜닝 없이 모델의 행동을 제어하는 directional steering, MTP 투기적 디코딩, 그리고 성능 검증을 위한 ds4-eval/bench 등 엔진의 내부 구조와 실험 기구들을 다룹니다.

핵심 포인트

  • Directional steering을 통해 파인튜닝 없이 모델의 답변 스타일 제어 가능
  • MTP 투기적 디코딩의 구현 방식과 가속화 한계 분석
  • 추론 경로의 무결성을 검증하는 ds4-eval 회귀 스위트 소개
  • 컨텍스트 프론티어별 스루풋을 측정하는 ds4-bench 활용

DeepSeek V4 전용 추론 엔진

DwarfStar(ds4)를 읽는 연재의 최종회. 주류에서 벗어나 온존해 왔던 「실험 기구」와 「주변 도구」를 한꺼번에 다룹니다. directional steering, MTP 투기적 디코딩 (speculative decoding), ds4-eval / ds4-bench, 그리고 자체 데이터 구조까지.

directional steering: 「거절은 단일 방향으로 매개된다」 논문의 응용. verbose/succinct 예시의 평균 차분으로 방향 벡터를 추출하고, y = y - scale·dir·(dir·y)를 FFN/attn 출력에 사영(projection). 파인튜닝 (fine-tuning) 없이 장황함이나 도메인 거절을 제어.

MTP 투기적 디코딩 (speculative decoding): 멀티 토큰 예측 드래프트(draft) + 타겟 검증. confidence margin 게이트 포함. 현재 미미한 가속화에 그치는 이유를 코드로 설명.

ds4-eval: GPQA Diamond / SuperGPQA / AIME2025 / COMPSEC를 92문제 포함한 회귀 스위트(regression suite). 리더보드가 아니라 「추론 경로가 망가지지 않았는지」를 검사.

ds4-bench: 전체 평균이 아니라 컨텍스트 프론티어 (context frontier) 별 순간 스루풋(throughput)을 측정.

  • 엔진 이외에도 자체 제작:
    rax (기수 트리 (radix tree)), linenoise (REPL), 독자적인 토크나이저 (tokenizer), official-vector 회귀 테스트.

논문 Refusal in Language Models Is Mediated by a Single Direction의 핵심은, 「모델의 어떤 행동(거절 등)은 활성화 공간 (activation space)의 단일 방향으로 매개될 수 있다」는 관찰입니다. DwarfStar는 이를 구현하여, 파인튜닝 없이 모델의 행동을 굴절시킵니다.

이를 사용하여 모델을 더 또는 덜 장황하게 만들거나, 만약 당신의 렌터카 웹사이트를 위한 챗봇이라면 프로그래밍 질문에 답할 확률을 낮추는 등... 파인튜닝보다 훨씬 빠르게 수행할 수 있습니다. 이는 또한 이중 용도(dual-use) 또는 공격적인 보안 가이드를 제공하려는 모델의 의지를 줄이고 싶어 하는 사이버 보안 연구자들에게도 유용합니다.

dir-steering/tools/build_direction.py는 쌍을 이루는 프롬프트 집합(예: verbose한 예시 vs succinct한 예시)의 활성화를 비교합니다.

# build_direction.py(개념): N_LAYER=43, N_EMBD=4096
# 각 쌍에서 활성화를 캡처하여 층(layer)별로 평균
for layer in range(N_LAYER):
...

활성화 캡처는 Metal 그래프 덤프 기구(환경 변수 DS4_METAL_GRAPH_DUMP_*)를 통해, 층별 ffn_out 또는 attn_out을 추출합니다. 출력은 2개 파일입니다.

verbosity.json: 메타데이터 (shape [43, 4096], component, 정규화 플래그)

verbosity.f32: 43층 × 4096 float의 플랫 바이너리 (layer-major, 약 688KB)

엔진은 각 층의 어텐션(attention)/FFN 출력에 방향을 사영하여 뺍니다.

// ds4.c: directional steering의 사영 (CPU 경로)
const float *dir = dirs + (uint64_t)il * DS4_N_EMBD; // 이 층의 방향
for (each row xr) {
...

식은 y = y - scale · dir · (dir·y)입니다. 이는 「활성화 벡터 y에서 방향 dir 성분을 scale 배만큼 빼는」 사영 연산입니다.

dir (이 층의 방향 벡터)
↑
│ y (활성화)
...

양(+)의 스케일: 해당 방향을 억제 (예: 장황함을 억제)

음(-)의 스케일: 해당 방향을 증폭 (예: 더 장황하게)

적용 위치는 engine option (ds4.h)의 directional_steering_attn / directional_steering_ffn에서 attn 출력 및 FFN 출력 각각에 스케일을 지정할 수 있습니다. README에서는 "FFN 출력이 첫 번째 타겟으로서 통상적으로 가장 좋다"라고 명시하고 있습니다. Metal 측에서는 metal_graph_apply_directional_steering_ffn/attn이 그래프에 포함되어, HC 전개 전 단계에서 적용됩니다. 가중치(Weight)와 파인튜닝(Fine-tuning)을 변경하지 않고, 포워드 패스(Forward pass)에 벡터 사영(Vector projection) 하나를 더하는 것만으로 동작을 굴절시킬 수 있다는 점이 강점입니다.

MTP(Multi-Token Prediction)는 DeepSeek V4의 옵션 기구로, **치환 샘플러(Replacement sampler)가 아니라 투기적 드래프터(Speculative drafter)**입니다. 코드의 주석이 간결합니다.

MTP in DeepSeek V4 is a speculative drafter, not a replacement sampler. The target model still defines the exact output stream.

사이클은 "(1) 통상적인 타겟 토큰을 하나 수락 → (2) MTP 블록에 짧은 후속 내용을 제안하게 함 → (3) 타겟 모델이 여러 제안 위치를 한꺼번에 검증"하는 흐름입니다. 제안이 도움이 되는 경우는 타겟이 여러 위치를 **일괄 검증(Batch verification)**할 수 있는 경우뿐입니다.

엔트리는 ds4_session_eval_speculative_argmax()입니다. MTP는 독립적인 작은 raw SWA 캐시와 핑퐁 버퍼(mtp_state_hc / mtp_next_hc)를 가지며, 드래프트 토큰을 재귀적으로 생성합니다. MTP의 첫 번째 드래프트가 타겟 로짓(Logits)의 argmax와 일치하지 않으면, 즉시 first_token만 출력하고 중단합니다(무의미한 계산을 방지하기 위함).

드래프트가 2토큰에 도달했을 때, 상위 2개 로짓의 차이(Margin)가 임계값(기본값 3.0, --mtp-margin) 미만이라면, 검증하지 않고 first_token만 출력합니다.

// 개념: 확신이 낮으면 검증 비용을 지불하지 않음
if (mtp_last_margin < mtp_margin_threshold) {
return n_accept; // 저확신 → 고속 패스로 1 토큰만
...

사이클 전체의 판정 플로우는 다음과 같습니다.

  • 모든 드래프트가 성공할 때만, 드래프트 수에 비례하여 가속화됨 (예: 2토큰일 때 2배).
  • Margin 게이트가 작동하면 1토큰만 출력 → 가속화 효과 없음 (게다가 드래프트 계산은 낭비가 됨).
  • 검증 실패 시에는 드래프트 작업이 모두 무효화됨.
  • 많은 프롬프트는 확신도가 낮아(margin < 3.0), 고속 패스로 떨어짐.
  • 타겟 + MTP의 듀얼 캐시 관리로 인해 메모리 대역폭(Memory bandwidth)에 대한 압박이 증가함.

README에서도 "현재의 MTP/투기적 디코딩(Speculative decoding)은 correctness-gated 방식이며, 기껏해야 약간의 가속화일 뿐, 생성 속도의 의미 있는 향상은 아니다"라고 명시하고 있습니다. --mtp MTP.gguf --mtp-draft 2로 활성화할 수 있으며, 탐욕적 디코딩(Greedy decoding)에서만 유용한 실험적 경로입니다. "투기적 디코딩을 진지하게 구현했지만, 이 모델과 이 환경에서는 효과가 미미하다"라고 솔직하게 밝히고 있는 점이야말로 회귀 검증(Regression verification)을 중시하는 이 프로젝트다운 부분입니다.

ds4-eval(약 4,000행)은 리더보드 러너가 아니라 **실제 모델 통합을 위한 회귀 스위트(Regression suite)**입니다. 92문항이 내장되어 있습니다.

  • 전반부 75문항: GPQA Diamond 25 + 검증된 SuperGPQA 25 + AIME2025 25를 교차 배치
  • 후반부 17문항: 공개 CVE에서 축약한 COMPSEC (C/C++의 취약점 위치 식별. 익스플로잇이 아니라 "방어 코드의 결함이 들어가는 최적의 한 줄"을 답함)
./ds4-eval -m ds4flash.gguf --trace /tmp/ds4-eval.txt

실제 GGUF를 로드하고, DS4 채팅 프롬프트 (Chat Prompt)를 렌더링하며, 샘플 토큰 (Sample Token)을 분할 화면 TUI로 스트리밍하고, 최종 답변을 채점합니다. 목표는 "커널, 양자화 (Quantization), 프롬프트 포맷팅 (Prompt Formatting), KV, 툴 스트림 (Tool Stream)에 변경을 가한 후에도, DeepSeek V4 Flash가 **동일한 추론 경로 (Inference Path)**에서 어려운 과학, 넓은 지식, 엄격한 수학, 보안 코드의 대표적인 혼합 문제를 여전히 풀 수 있는가"를 묻는 것입니다. 만점 92/92는 예상되지 않으며, 이를 **하드한 능력 회귀 스위트 (Hard Capability Regression Suite)**로 사용합니다.

결정적인 회귀 게이트 (Regression Gate)도 준비되어 있습니다.

./ds4-eval -m ds4flash.gguf --plain --questions 4 --tokens 2048 --temp 0 --seed 1

q1..q4의 생성 토큰 수가 베이스라인과 일치하는지 확인합니다 (예: q1은 PASSED/2048토큰/B・B). 이는 추론 변경으로 인한 생성 드리프트 (Generation Drift)를 조기에 탐지하기 위한 장치입니다. --regrade-trace를 사용하면 모델을 다시 로드하지 않고 과거 트레이스 (Trace)에 대해 채점기만 재적용하여, 평가기 (Evaluator)의 변경 사항을 감사할 수 있습니다.

ds4-bench (약 600행)는 전체 실행의 평균이 아니라 컨텍스트 프런티어 (Context Frontier)별 순간 Prefill/생성 처리량 (Throughput)을 측정합니다. 모델을 한 번 로드한 뒤, 고정된 토큰 열을 2048, 4096, 61436, ... 순으로 진행하며 증분 Prefill을 통해 "새로 추가된 구간만"을 측정합니다. 각 프런티어에서 라이브 KV를 메모리에 저장하고, 고정된 탐욕적 비-EOS 프로브 (Greedy non-EOS probe)를 생성한 뒤, 스냅샷을 복원하여 Prefill을 계속합니다.

./ds4-bench -m ds4flash.gguf --prompt-file speed-bench/promessi_sposi.txt \
--ctx-start 2048 --ctx-max 65536 --step-incr 2048 --gen-tokens 128

출력은 CSV 형식이며 (프런티어별 Prefill t/s, 생성 t/s, kvcache_bytes), "긴 컨텍스트에서 속도가 어떻게 저하되는가"를 하나의 곡선으로 볼 수 있어, 제3회에서 다룬 압축 어텐션 (Compressed Attention)의 효과를 정량화할 수 있습니다. 벤치마크용 텍스트는 저작권이 만료된 Project Gutenberg (만조니의 『좋은 아내』)입니다.

DwarfStar는 추론 엔진 외에도 외부 의존성을 피하고 자체적으로 보유하고 있습니다.

  • rax.c (약 2,700행): 기수 트리 (Radix Tree). 제5회의 exact replay 맵 (tool id → DSML 블록)의 토대입니다. antirez가 Redis를 위해 작성한 rax를 유용했습니다.
  • linenoise.c (약 2,700행): 가벼운 행 편집 REPL. CLI의 대화형 입력에 사용됩니다. 이 또한 antirez의 작품입니다.
  • 독자적인 토크나이저 (Tokenizer): DS4의 프로토콜 특수 토큰 (`</`, `|DSML|` 등)을 인식합니다. ./ds4 --dump-tokens를 통해 토크나이즈 결과만 확인하고 종료할 수 있습니다. 예를 들어 DSML의 툴 종료 마커는 `</``|DSML|`라는 2개의 토큰으로 시작한다는 점 등을 검증할 수 있습니다.
  • official-vector 회귀 테스트: tests/test-vectors에 공식 DeepSeek V4 Flash API에서 가져온 단문/장문 컨텍스트 지속 벡터를 배치하고, ./ds4 --dump-logprobs의 로컬 결과와 토큰 바이트 단위로 비교합니다. 토크나이저/템플릿/어텐션의 퇴행이 긴 생성 실패로 이어지기 전에 탐지됩니다.
make test # ./ds4-eval --self-test-extractors && ./ds4_test --all
./ds4_test --logprob-vectors

디버깅을 위한 '세 가지 신기'를 기억해 두면 편리합니다.

./ds4 --dump-tokens -p "..." # 토크나이즈만 수행
./ds4 --dump-logprobs /tmp/out.json --temp 0 -p "..." # 탐욕적 지속 + 상위 후보
./ds4-server --trace /tmp/ds4-trace.txt ... # 세션 전체의 트레이스

전 8회에 걸쳐 나타난 DwarfStar의 설계 사상을 마지막으로 정리하겠습니다.

  • 1모델 특화라는 도박 (제1회): 범용성을 버리고, DeepSeek V4를 엔드투엔드 (end-to-end)로 완성시킨다.
  • 아키텍처 특화 양자화 (Quantization) (제2회): 대략적인 파라미터의 대부분을 차지하는 routed experts를 주 대상으로 2bit화하고, imatrix를 통해 오차를 중요한 열로 집중시킨다 (q2-q4 mixed 등 레시피 차이도 존재).
  • 압축 KV 구현 (제3회): compressor/indexer/HC/tail-RoPE를 Metal 그래프에 수직 통합한다.
  • KV는 디스크의 일급 시민 (제4회): 렌더링 바이트를 키 (key)로 하여, 세션을 넘나들며 재사용한다.
  • API 호환과 DSML 밀결합 (제5회): exact replay를 통해 도구 호출 (tool calling)과 KV를 맞물리게 한다.
  • 분산의 비대칭성 (제6회): prefill은 빠르고, 생성은 느리다는 점을 솔직하게 설계한다.
  • 세션 = KV의 에이전트 (Agent) (제7회): 정합성 문제를 구조 자체로 제거한다.
  • 정직한 실험 기구와 검증 기반 (제8회): steering/MTP/eval/bench를 통해 "효과가 있는가·망가지지 않았는가"를 계속해서 측정한다.

관통하는 핵심은, **"로컬 추론을, 하나의 모델로, 박스에서 꺼내자마자 바로 사용할 수 있는 상태까지 만들어낸다"**라는 일관된 자세입니다. 엔진 본체는 beta, 에이전트는 alpha라는 진행 중인 품질임에도 불구하고, A) 엔진+API, B) 전용 GGUF, C) 에이전트 검증이라는 삼위일체가 확실히 하나의 형태로 구축되어 있습니다.

Redis 제작자가 C 언어로 작성한 LLM 추론 엔진 ―― 이 글의 묘미는 화려한 최적화보다 "무엇을 버리고, 무엇에 걸었는가"라는 설계 판단의 명쾌함에 있습니다. 코드를 읽으며 그 판단을 함께 재경험하실 수 있다면 좋겠습니다.

항목위치
방향 추출 (Direction Extraction)dir-steering/tools/build_direction.py
steering 적용ds4.c cpu_directional_steering_project_rows()
MTP 투기 (Speculative)ds4.c ds4_session_eval_speculative_argmax()
평가 스위트 (Eval Suite)ds4_eval.c
벤치 (Bench)ds4_bench.c
기수 트리 (Radix Tree) / REPLrax.c / linenoise.c
회귀 벡터 (Regression Vectors)tests/test-vectors/

본 기사는 퀵 이터레이트 주식회사 (Quick Iterate Co., Ltd.)의 로컬 LLM 연구의 일환으로, 공개 리포지토리 antirez/ds4의 코드를 분석한 것입니다. 행 번호·상수·벤치 값은 열람 커밋 ba00a8a (2026-05-30) / README 취득일 2026-06-01 시점의 것입니다. ds4-agent는 alpha, 엔진 본체는 beta 품질로 활발하게 변화하므로, 인용 부분은 각자 최신 README / 소스를 확인하여 재확인하시기 바랍니다.

퀵 이터레이트 주식회사 (Quick Iterate Co., Ltd.)

IoT / 전력 모니터링 / AI / 위성·무선 통신 / 시스템 통합 (System Integration)/

로컬 LLM·에이전트 기반에 관한 문의는 언제든 환영합니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0