본문으로 건너뛰기
5분 AI.
TRENDSHIFT WEEKLY #3 딥다이브 · 2026-10-23 분석

DeepInfer 딥다이브
— 거대한 모델보다 먼저 이해할 요청·메모리·병렬 처리

추론 프레임워크

빠른 판단

무엇
DeepSeek 모델의 배치·메모리·전문가 병렬화·커널 실행을 조율하는 분산 오프라인 추론 프레임워크
이럴 때
여러 가속기에서 DeepSeek 입력 목록을 처리하거나 배치 스케줄링과 분산 메모리 설계를 연구할 때
입력
모델·병렬화 설정과 LLM.generate()에 전달할 입력 목록
결과
분산 배치 추론으로 생성한 결과 목록
AI가 답변 한 글자를 내놓기까지, CPU는 어떤 요청을 고르고 GPU는 무엇을 기다릴까요? DeepSeek의 추론 프레임워크 DeepInfer를 Python 진입점부터 C++ 스케줄러와 장치별 커널까지 따라갑니다. 고가의 장비가 없어도 코드 읽기와 손으로 하는 실험을 통해 빠르면서도 결과가 안정적인 시스템을 설계하는 법을 배웁니다. 저장소 deepseek-ai/DeepInfer · 스타 20,308 · 포크 2,186 · Python · Apache-2.0. GitHub 메타데이터는 2026-10-23 기준이며, 소스 설명은 커밋 9bd9cf2 기준입니다.
목차 · 기초 개념에서 실제 설계까지
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

모델이 답을 만드는 동안, 계산 자원이 쉬지 않게 하는 엔진

DeepInfer는 DeepSeek 모델을 여러 가속기에 나누어 올리고, 요청·메모리·연산 순서를 조율하는 추론 프레임워크입니다. README는 DeepSeek의 대규모 운영 서비스에 사용되는 프레임워크라고 소개합니다. 다만 공개된 버전의 사용 흐름은 LLM.generate()에 입력 목록을 주고 결과를 받는 오프라인 추론입니다. 모델 자체의 지식을 학습하는 훈련 코드와는 역할이 다릅니다. 출처: README.

먼저 알아둘 말
추론과 토큰
추론은 이미 학습한 모델로 새 입력의 답을 계산하는 과정입니다. 토큰은 모델이 읽고 쓰는 단위로, 단어 전체일 수도 있고 단어 조각일 수도 있습니다. “안녕하세요”가 언제나 한 토큰인 것은 아닙니다. 문장을 토큰 번호로 바꾸는 부품이 토크나이저입니다.

초보자가 이 저장소에서 얻을 수 있는 가장 큰 수확은 거대한 신경망의 수식을 모두 외우는 일이 아닙니다. 모델 한 번을 빠르게 계산하는 문제와, 수많은 요청을 빠짐없이 처리하는 문제를 함께 보는 법을 배울 수 있습니다. 행렬곱이 빨라도 요청을 고르느라 GPU를 기다리게 하거나, 사용 중인 메모리를 일찍 반납하면 시스템 전체는 느려지거나 잘못 동작합니다.

핵심 비유

모델이 요리사라면, DeepInfer는 대형 식당의 주방 운영 체계입니다

레시피를 잘 아는 요리사만으로 주문 수천 건을 제시간에 내보낼 수는 없습니다. 주문을 묶고, 재료 공간을 배정하고, 어느 조리대가 일을 맡을지 정해야 합니다. 이 저장소에서 Scheduler는 주문 담당자, BlockManager는 재료 보관함 관리자, Worker는 조리대 작업 담당자에 가깝습니다.

이미 손질한 재료를 다시 손질하지 않는 것이 캐시 재사용입니다. 여러 메뉴를 동시에 준비하되 완성된 접시를 다른 주문과 섞지 않는 것이 배치 처리와 요청별 상태 관리입니다.

사용자에게 보이는 간단한 표면, 내부의 긴 실행 경로

deepinfer/entrypoints/llm.py의 LLM.generate()는 단일 문자열을 목록으로 정규화하고, 각 입력을 _add_request()로 등록합니다. 여기서 샘플링 설정은 copy.deepcopy()로 복사하고 토큰 번호는 np.int32 배열로 맞춥니다. 이어 _run_engine()이 반복해서 엔진을 진행시킵니다.

# 소스의 호출 순서를 요약한 개념도입니다. 실행용 코드가 아닙니다.
문자열 또는 토큰 번호 목록
    → LLM.generate()
    → LLM._add_request()
    → LLMEngine.add_request()
    → LLM._run_engine() 안에서 step() 반복
    → 남아 있는 비동기 결과 flush_inflight_reqs()
    → 요청 번호 순으로 정렬하고 필요하면 문자열로 복원
읽기 목표
이 글을 읽고 설명할 수 있어야 하는 세 가지

왜 요청을 하나씩 처리하지 않고 묶는지, 왜 GPU가 끝나기 전에 CPU가 다음 일을 시작하는지, 왜 결과를 반환한 뒤에도 메모리 수명을 신경 써야 하는지 설명해 보세요. 이 세 질문에 답하면 복잡한 최적화 코드를 읽을 기준이 생깁니다.

2왜 주목받는가

공개 직후의 관심과, DeepSeek에 집중한 설계의 가치

2-1. 관심의 크기와 관심의 이유는 구분해서 읽기

선정 근거는 TrendShift Weekly #3(2026-10-23)입니다. GitHub 메타데이터에 따르면 2026-10-16에 생성된 저장소가 2026-10-23 기준 스타 20,308개, 포크 2,186개를 모았습니다. 약 일주일 된 공개 저장소라는 점은 관심의 크기를 보여 줍니다. 다만 스타·포크 수와 관심도 순위만으로 실제 사용자 수나 성능 우위를 판단할 수는 없습니다.

코드를 읽는 관점에서 주목할 이유는 명확합니다. README에서 소개하는 FlashMLA·DeepGEMM·DeepEP 같은 연산·통신 부품이 실제 요청 처리 루프 안에서 어떻게 이어지는지 볼 수 있습니다. “빠른 커널 하나”와 “빠른 추론 시스템” 사이를 공부하기 좋은 자료입니다.

2-2. 범용 도구와 다른 선택: 지원 범위를 좁히고 내부를 깊게 최적화

README의 지원 모델은 DeepSeek-V4.1-Flash 하나입니다. 실제 ModelRegistry에도 DeepseekV41ForCausalLM 아키텍처 하나가 등록되어 있습니다. DeepInfer의 학습 가치는 지원 모델의 개수보다, 특정 모델과 하드웨어에 맞춰 시스템 전체를 조율한 코드에 있습니다. 모델 이름을 바꾸기만 하면 모든 Hugging Face 모델이 동작한다고 해석하면 안 됩니다.

도구공식 자료에서 확인한 사용 표면DeepInfer와 비교하며 배울 점
DeepInfer특정 DeepSeek 모델의 오프라인 추론. 내부 스케줄러·병렬 실행·커널 연결 공개모델 구조에 맞춘 메모리 배치와 실행 순서의 구체성이 장점. 온라인 서비스 구성은 추가 작업
vLLM온라인 서빙과 OpenAI 호환 HTTP 서버 사용법 제공API 서비스 표면과 내부 엔진을 구분해 보기. DeepInfer README도 vLLM을 주요 출발점으로 명시
SGLangPrefill/Decode 분리와 Mooncake·NIXL 등의 전송 설정 문서 제공엔진 사이 KV 전달과 라우터 연결까지 공부할 때 비교할 자료
TensorRT-LLM분리 서빙에서 context·generation 서버와 조정 서버를 구성하는 예제 제공GPU 실행 최적화가 실제 온라인 요청 경로와 결합하는 방법 비교

경쟁 도구의 설명은 각각의 공식 문서 vLLM 온라인 서빙, SGLang 단계 분리, TensorRT-LLM 분리 서빙에 근거합니다. 동일 장비·동일 모델의 직접 성능 비교표가 아니며, 어느 기능을 DeepInfer만 제공한다고 주장하는 표도 아닙니다.

2-3. 성능 그래프를 볼 때 먼저 읽어야 할 작은 글씨

README의 성능 그래프는 prefill에 SM100 GPU 4개, decode에 64개를 사용했고, 각각 하나의 고속 상호 연결 영역 안에서 측정했다고 적습니다. 이 조건을 지우고 개인용 GPU 한 장의 속도로 받아들이면 비교가 무너집니다. 이 글에서는 그래프 이미지를 보고 수치를 추정하거나 자체 측정 결과처럼 재인용하지 않습니다.

성능을 읽는 기준
처리량과 지연 시간
처리량은 일정 시간에 전체가 처리한 양입니다. 지연 시간은 한 요청이 기다린 시간입니다. 식당이 한 시간에 1,000그릇을 만들어도 내 한 그릇이 30분 뒤에 나오면 체감은 느립니다. 배치를 크게 만드는 최적화는 두 지표를 서로 다르게 움직일 수 있습니다.

examples/README.md는 decode 처리량이 실제 초안 토큰의 채택률과 무관하게 1 + nextn개를 세는 전부 채택된다고 가정한 환산치라고 명시합니다. 프로파일러를 붙인 구간의 시간도 처리 속도를 산출하는 데 쓰지 말라고 설명합니다. 벤치마크를 배울 때는 큰 숫자보다 무엇을 분모·분자로 세었는지가 먼저입니다.

3기술 스택 전체 지도

Python 제어부, C++ 엔진, 장치 커널, 빌드 경로를 따로 읽기

3-1. 백엔드: 같은 Python 파일도 서로 다른 층에서 일한다

Python은 요청 API와 모델 실행뿐 아니라 TileLang 커널을 기술하는 언어로도 쓰입니다. 따라서 Python 줄 수가 많다고 CPU에서만 계산하는 프로그램은 아닙니다. 반대로 csrc/의 C++는 주로 스케줄링·입력 메타데이터·바인딩을 담당합니다. 대규모 연산 라이브러리의 구현 전체는 외부 의존성에 걸쳐 있습니다.

층실제 의존성·버전역할과 확인 파일
Python 패키지deepinfer 0.1.0, Python >=3.12pyproject.toml. 개발 상태는 Beta로 표시
NVIDIA 런타임torch==2.13.0+cu132, flash-attn-4==4.0.0b34requirements-nvidia.txt. 일반 PyTorch와 CUDA 변형을 혼동하지 않기
Ascend 런타임torch==2.13.0+cpu, torch-npu==2.13.0rc1requirements-ascend.txt. CPU 표기 PyTorch에 NPU 지원 패키지를 결합
모델 입출력transformers==4.50.0, tokenizers==0.21.4모델 설정·토크나이저를 연결하는 deepinfer/hugging_face/
가중치 파일safetensors==0.8.0, huggingface_hub==0.36.2가중치 읽기와 체크포인트 경로 해석. 다운로드 진입점은 examples/_config.py
수치·자료 배치numpy==2.3.5, einops==0.8.2CPU 토큰 배열과 다차원 텐서 재배열
장치 커널tilelang==0.1.15, tile-kernels==2.1.0deepinfer/model_executor/layers/tilelang_ops/의 인터페이스 및 CUDA·Ascend 구현
형식 제약xgrammar==0.2.2JSON Schema·정규식·EBNF로 다음 토큰의 허용 범위를 제한
프로세스 통신pyzmq==27.1.0, posix_ipc==1.3.2프로세스 간 메시지 및 공유 메모리 경로에 사용하는 의존성

버전의 1차 근거는 requirements.txt, requirements-nvidia.txt, requirements-ascend.txt입니다. 표의 값은 해당 커밋의 의존성 선언입니다. 실제 설치 환경은 플랫폼별 요구사항에 맞춰야 합니다.

3-2. 프론트엔드와 HTTP: 웹 제품의 구조로 오해하지 않기

현재 커밋에는 웹 UI용 package.json, React·Vue 앱이나 브라우저 화면 코드가 없습니다. 사용자가 만나는 표면은 Python API와 examples/의 명령행 예제입니다. FastAPI==0.128.0과 uvicorn==0.40.0은 requirements-dev.txt에 있지만, 이것만 보고 대화형 HTTP 추론 서버가 있다고 결론 내리면 안 됩니다.

실제 deepinfer/engine/profile_server.py는 POST /profile로 실행 추적을 수집하는 선택적 프로파일링 서버입니다. DEEPINFER_PROFILE_HTTP_ENABLE의 기본값은 꺼짐이며, 포트는 기본 6070 + driver_gpu_id입니다. 추론 서비스 API와 관측용 API를 구분하는 좋은 예입니다.

3-3. 인프라·빌드: pyproject의 하한과 실제 선택 버전이 다르다

pyproject.toml의 빌드 의존성은 setuptools >= 77.0.3, torch >= 2.7, ninja입니다. 플랫폼별 requirements의 PyTorch 고정 버전과 역할이 다릅니다. 빌드 도구의 최소 버전 선언은 이 저장소가 실제로 맞춰 놓은 실행 환경 전체를 뜻하지 않습니다.

# build.sh와 scripts/build.sh의 주요 처리 순서
build.sh
  → requirements-nvidia.txt 또는 requirements-ascend.txt 선택
  → NVIDIA이면 nvidia-nccl-cu13==2.32.3으로 교체
  → scripts/build_vendor.sh: 서브모듈 초기화와 wheel 빌드
  → scripts/build.sh build: setup.py로 deepinfer._C 빌드
  → deepinfer/_so/{플랫폼}-{아키텍처}/ 아래에 확장 연결

setup.py는 공통 컴파일 옵션 -O2, -std=c++20, _GLIBCXX_USE_CXX11_ABI=1을 사용합니다. NVIDIA는 CUDAExtension, Ascend는 NpuExtension을 선택합니다. scripts/build.sh의 기본 병렬 빌드 수 MAX_JOBS는 16입니다. 단순 Python 패키지 설치와 달리 컴파일러·ABI·가속기 SDK가 함께 맞아야 합니다.

외부 서브모듈HEAD가 고정한 커밋 앞부분역할
DeepEPf6aa38feMoE 전문가 사이의 토큰 통신
DeepGEMM1fc9c669행렬곱·MoE 연산 경로
FlashMLA2e5429fc어텐션 연산 가속 경로
DeepSelectbfa4507d희소 어텐션의 후보 선택 경로
Ascend 변형DeepEP 3b25377d, DeepGEMM 3a353262같은 역할을 Ascend용 구현으로 연결

.gitmodules의 URL과 git ls-tree HEAD vendor/의 커밋 참조가 외부 의존성을 지정합니다. 외부 구현은 별도 저장소에 있으며 빌드 시 서브모듈 초기화가 필요합니다. 여기서는 DeepInfer 쪽 호출·연결 구조를 다룹니다.

3-4. 개발 품질 도구와 공개 자동화의 경계

requirements-dev.txt에는 pytest==8.4.2, pytest-xdist==3.8.0, ruff==0.15.0, clang-format==22.1.3이 있습니다. pyproject.toml은 Ruff의 줄 길이를 140으로 설정하고, pytest의 기본 검색 경로를 tests로 지정합니다. import 단계의 무거운 의존성 유입을 줄이기 위한 --import-mode=importlib 설정도 확인됩니다.

커밋 9bd9cf2의 추적 파일에는 Dockerfile, .github/workflows/, GitLab CI 설정이 없습니다. 반면 CONTRIBUTING.md와 pytest 설정에는 ci·ci_npu 마커가 있습니다. 테스트를 분류하는 규칙은 공개되어 있지만, CI 실행 파이프라인까지 공개되어 있다고 볼 근거는 없습니다.

4아키텍처 심화 분석

요청 하나를 따라가며 만나는 네 가지 설계 패턴

4-1. 전체 구조: 요청 제어와 장치 계산을 연결하기

아래는 소스의 책임 경계를 단순화한 시스템 구조도입니다. Python과 C++가 각각 하나의 서버라는 뜻은 아닙니다. C++ 엔진은 deepinfer._C 확장으로 Python에서 호출됩니다. Worker는 병렬 구성에 따라 여러 프로세스·장치로 확장되며, 이 그림은 모든 통신 채널을 나열한 배포도가 아닙니다.

[입력: 문자열 / 토큰 번호 / 선택적 이미지] | v [Python API: LLM.generate / _add_request] | v [LLMEngine: 요청 등록 · 상태 관리 · 단계 진행] | | | pybind11 | 문법이 있는 요청 v v [C++ Scheduler] [SOMatcherBuilder] waiting / running 비동기 문법 컴파일 prefill / decode 선택 준비 후 스케줄러에 등록 | v [BlockManager: 장치 메모리 블록과 상태 슬롯 관리] | v [Worker.execute_model_step] | v [ModelRunner: 입력 준비 → 모델 계산 → 샘플링] | +---- [모델: DeepseekVLForCausalLM / DFlash] | +---- [공통 커널 인터페이스 → cuda / asc 구현] | +---- [프로세스 그룹: DP / CP / EP · 통신 라이브러리] | v [비동기 후처리 → 출력 복사 → 순서 복원 → 결과] [별도로 구성할 서비스 계층] 장기 KV 저장 시스템 · VE/Prefill/Decode 분리 운영 · 복제본 부하 분산
같은 추론 안의 두 단계
Prefill과 Decode
Prefill은 입력 문장을 읽고 이후 계산에 쓸 상태를 준비하는 단계입니다. Decode는 그 상태를 참조해 다음 출력 토큰을 이어 만드는 단계입니다. 입력 10,000토큰을 읽는 일과 답 1토큰을 추가하는 일은 작업 크기가 달라, 같은 배치 정책이 항상 최적이지 않습니다.

4-2. 패턴 ①: 사용하기 쉬운 API와 자원 판단의 분리

LLM이 입력 형식을 맞추면 LLMEngine이 요청 상태와 Worker 호출을 조율합니다. 배치의 실행 대상을 고르는 핵심은 csrc/engine/scheduler.hpp의 Scheduler::_schedule()·_schedule_prefill()·_schedule_decode()입니다. 애플리케이션 코드가 GPU 메모리 블록을 직접 골라야 하는 구조를 피한 셈입니다.

_schedule()은 py::gil_scoped_release로 Python의 GIL을 놓고, BlockManagerMutexAcquire로 블록 관리자와 상태 관리자를 잠급니다. Python 스레드를 계속 막아 두지 않는 것과 공유 자원을 안전하게 보호하는 것은 별개의 문제입니다. “C++로 바꾸면 빨라진다”보다 언제 잠그고 언제 다른 실행을 허용하는지를 읽어야 합니다.

엔진 종류소스의 분기교육적으로 볼 지점
NORMALprefill과 decode를 선택DP 그룹의 구성원들이 같은 단계로 움직이도록 투표
PROMPT_schedule_prefill()입력 처리 전용 엔진을 만들 수 있는 내부 경계
COMPLETION_schedule_decode()출력 생성 전용. prefill 경로가 없으므로 선점 시 재계산 정책에도 제약

NORMAL은 기본 70 decode 단계마다 모든 rank가 prefill 조건을 충족하는지 확인하고, 기본 100단계마다 한 rank라도 조건을 충족하면 prefill을 시도합니다. 조건은 캐시 사용률 90% 이하이면서 waiting 큐의 맨 앞 요청이 스케줄 가능한 상태인 것입니다. 두 주기가 겹치면 100단계 규칙을 적용하며, prefill 직후 decode 단계 수가 0일 때도 전원 조건을 확인합니다. 설정은 DEEPINFER_PREFILL_ATTEMPT_INTERVAL·DEEPINFER_PREFILL_ANY_ATTEMPT_INTERVAL입니다. 이는 초 단위 타이머가 아닙니다. 여러 rank가 서로 다른 집단 통신을 호출해 멈추지 않도록 단계 종류를 맞춥니다.

첫 투표에서 prefill을 원했어도 슬롯이나 KV 블록 부족으로 실제 배치가 비면, _schedule()은 두 번째 투표로 전원이 빈손인지 확인하고 decode로 돌아갑니다. 자원은 없는데 빈 prefill만 반복하는 상황을 막는 장치입니다. 분산 시스템에서는 일을 하고 싶다는 상태와 실제 일을 배정했다는 상태를 분리해야 한다는 사례입니다.

자원 부족도 단순한 참·거짓이 아닙니다. BlockManager::can_allocate_nolock()는 다음처럼 현재 가능·나중에 가능·구조적으로 불가능을 나눕니다. 아래는 해당 함수의 본문입니다.

AllocStatus can_allocate_nolock(int to_allocate_blocks) {
    if (to_allocate_blocks >= num_blocks) {
        return AllocStatus::NEVER;
    }
    if (blocks.num_free_blocks() >= to_allocate_blocks) {
        return AllocStatus::OK;
    }
    return AllocStatus::LATER;
}

블록 번호 0은 비어 있음을 뜻하도록 예약됩니다. 그래서 총 블록 수가 8이면 실제 사용 가능한 번호는 1~7입니다. LATER는 다른 요청이 메모리를 돌려주면 진행할 수 있다는 뜻이고, NEVER는 기다리기만 해서는 해결되지 않는 크기라는 뜻입니다. 이 구분은 작업 큐·연결 풀·업로드 용량 제한 같은 일반 백엔드에도 적용할 수 있습니다.

4-3. 패턴 ②: 비동기 파이프라인과 명시적인 자원 수명

Worker.execute_model_step()의 순서는 특히 중요합니다. 현재 단계의 모델 계산을 먼저 내보내고, 이전 단계의 결과를 후처리한 뒤, 현재 단계의 샘플링을 시작합니다. ZOS가 켜진 decode에서는 현재 결과의 후처리를 다음 호출로 미룹니다. prefill이나 ZOS가 꺼진 경우에는 현재 결과를 그 자리에서 처리합니다.

개념적인 시간 흐름 ──────────────────────────────→ 직렬 처리 CPU: [배치 n 준비] [결과 n 정리] [다음 준비] 장치: [계산·샘플링 n] [대기] ZOS decode의 핵심 순서 CPU: [현재 배치 준비] [이전 결과 후처리] [현재 샘플링 준비] 장치: [현재 모델 계산────────] [샘플링] ↑ CPU 후처리와 겹칠 수 있는 구간 현재 결과의 후처리: 다음 execute_model_step()에서 수행 마지막에 남은 결과: flush_inflight_reqs()로 회수 ※ 실제 소요 시간 비율이나 모든 stream의 타이밍을 표시한 그림은 아닙니다.

비동기 최적화의 핵심은 기다림을 뒤로 미루면서도, 아직 쓰는 데이터의 수명을 함께 늘리는 것입니다. WorkerStepState는 이전 단계의 메타데이터·샘플링 결과·완료 이벤트를 보관합니다. _post_process_step()은 sample_end_evt.synchronize() 이후에 후처리를 시작합니다. ZOS라는 이름은 동기화가 완전히 사라진다는 뜻이 아니라, CPU 작업을 장치 계산과 겹치게 하는 설계 의도를 나타냅니다.

deepinfer/engine/llm_engine.py의 DeferredRelease는 메타데이터·출력과 복제 작업의 자원을 모았다가 안전한 지점에서 해제합니다. 더 바깥의 LLM._run_engine()도 반환받은 출력을 RequestOutput.clone(raw_output)으로 복사합니다. 코드에 적힌 이유는 원본 출력이 다음 단계에서 회수될 수 있기 때문입니다.

소유권을 이해하는 비유

공용 칠판에 적힌 답을 다른 팀이 곧 지울 예정이라면, 내가 오래 보관할 답은 따로 옮겨 적어야 합니다. 원본 결과를 빌려 쓰는 것과 복사해서 소유하는 것은 다릅니다. 비동기 시스템에서 복사를 없애려면 먼저 “누가 언제까지 지우지 않을 것인가”라는 약속이 필요합니다.

4-4. 패턴 ③: 공통 인터페이스 뒤의 장치별 구현

deepinfer/platform.py의 PlatformGPU는 tilelang_ops_backend="cuda"와 distributed_backend="nccl", PlatformNPU는 "asc"와 "hccl"을 선택합니다. 상위 모델 코드에 장치별 조건문을 계속 늘리는 대신 선택 지점을 모은 구조입니다.

deepinfer/model_executor/layers/tilelang_ops/ops.py는 선택된 백엔드 디렉토리를 읽고 이름이 _tl로 끝나는 공개 커널 팩토리를 내보냅니다. 같은 이름이 충돌하면 assert로 잡고, 없는 커널을 요청하면 KernelUnavailableError를 냅니다. 함수 이름을 맞추는 계약과 누락을 드러내는 실패 경로까지 인터페이스 설계의 일부입니다.

# 실제 norm 관련 파일의 책임을 정리한 경로입니다.
deepinfer/model_executor/layers/tilelang_ops/norm.py
  norm(): 텐서 모양·stride·출력 공간과 옵션을 준비
      |
      v
deepinfer/model_executor/layers/tilelang_ops/ops.py
  현재 플랫폼의 norm_tl 선택
      |
      +→ deepinfer/model_executor/layers/tilelang_ops/cuda/norm.py: @tilelang.jit(target="cuda")
      +→ deepinfer/model_executor/layers/tilelang_ops/asc/norm.py: Ascend 백엔드 구현

CUDA의 norm_tl()은 0 < d <= 8192를 검사하고, 기본 128 threads에서 벡터화·패딩·점유율을 고려해 실행 구성을 조절합니다. 공통 norm()은 RMSNorm에 residual 덧셈과 FP8 변환을 함께 처리하는 옵션을 제공합니다. 중간 결과를 장치 메모리에 여러 번 쓰고 읽는 일을 줄이는 연산 융합을 배울 수 있는 진입점입니다.

NPU 경로는 단순히 cuda라는 이름을 바꾸는 것으로 끝나지 않습니다. PlatformNPU.__init__()에는 transfer_to_npu, TILELANG_DEFAULT_TARGET="ascend", 장치 가시성 변수 검사가 있습니다. 공통 API를 제공하면서도 런타임 초기화 차이는 별도로 다룬다는 점이 핵심입니다.

4-5. 패턴 ④: 실제 작업량을 관찰하고 다음 배치를 조정

MoE는 토큰마다 일부 전문가 신경망을 선택합니다. 전문가 수가 같아도 특정 전문가로 토큰이 몰리면 그 전문가를 가진 장치가 병목이 됩니다. rebalance_experts_global()은 과거 토큰 수 [단계, MoE 층, 논리 전문가]를 받아 인기 전문가에 복제본을 추가하고 물리 배치를 다시 정합니다.

_batch_greedy_indices()는 복제본당 부하를 기준으로 전문가를 정렬한 뒤, 각 후보 rank에 놓았을 때 과거 각 단계의 최대 rank 부하를 더한 값이 작아지도록 탐욕적으로 배치합니다. 평균 부하만 같게 만드는 것보다, 같은 순간에 같이 바빠지는 전문가를 나누는 데 초점이 있습니다. 전역 최적해를 보장하는 수학적 최적화라고 단정해서는 안 됩니다.

병렬화의 단위
DP · CP · EP · EPLB
DP는 서로 다른 요청의 처리를 나누고, CP는 한 문맥의 계산을 나누며, EP는 MoE 전문가를 나눠 배치하는 개념입니다. EPLB는 전문가별 부하를 보고 복제·배치를 조정하는 정책입니다. 이 저장소의 프로세스 그룹은 deepinfer/model_executor/parallel_utils/parallel_state.py에서 구성됩니다.

초안 토큰 검증에도 피드백을 사용합니다. ConfidenceHead.forward()는 초안 토큰의 채택 가능성을 추정합니다. csrc/engine/mtp_varlen.hpp의 스케줄링은 그 추정치와 decode 성능 곡선을 이용해 검증할 길이를 정합니다. CPU에 도착한 추정치가 몇 단계 전 결과인지까지 구분하는 코드가 있어, 비동기 통계의 시차도 관찰할 수 있습니다.

4-6. 계산을 줄이는 경로와 출력을 제한하는 경로

DSpark 초안 생성은 다음 후보를 미리 만들고 주 모델이 검증하게 하는 방식입니다. DEEPINFER_USE_NEXTN_DECODE의 기본값은 5이고, 신뢰도 기반 가변 길이 검증은 DEEPINFER_ENABLE_MTP_VARLEN=1로 켭니다. 후보를 5개 만든다고 매번 최종 답 5개가 추가로 확정되는 것은 아닙니다.

YoCo의 bounded replay는 지원되는 모델 구조에서 consumer 층에 필요한 끝부분만 다시 처리하도록 줄이는 경로입니다. deepinfer/model_executor/models/v4_modules/yoco.py의 compact_yoco_boundary()는 hidden·residual과 관련 인덱스를 재배열하고, 기존 query 행 배치에 의존한 후보 캐시를 비웁니다. 앞부분을 줄였는데 예전 인덱스를 그대로 쓰면 안 된다는 점이 일반적인 배열 최적화와도 연결됩니다.

구조화 출력은 또 다른 목적입니다. deepinfer/structure_output/compiler.py의 dispatch_and_compile()은 json·regex·ebnf를 분기하고, JSON은 strict_mode=True로 컴파일합니다. SOMatcherBuilder.submit()이 작업을 맡기고 pump()가 준비된 요청을 스케줄러에 넣습니다. 형식 제약을 컴파일하는 CPU 작업이 전체 추론 루프를 막지 않도록 한 구조입니다.

문법에 맞는 JSON이라고 내용까지 참인 것은 아닙니다. 출력의 형식 검사와 답변의 의미 검증을 구분하세요. 이 구분은 API 응답 검증, 데이터 파이프라인, AI 애플리케이션의 결과 처리에서도 그대로 필요합니다.

아래는 실제 SamplingParams 인자 형태를 보여 주는 독해용 예시입니다. 네 자리 숫자라는 문법 제약을 전달합니다. max_tokens는 토큰 수의 상한이므로 글자 수 조건과는 다릅니다. 출력 형식은 정규식으로, 최대 생성 길이는 토큰 수로 각각 제한합니다.

# SamplingParams에 정규식 제약 전달
from deepinfer.sampling_params import SamplingParams

params = SamplingParams(
    temperature=0.0,
    max_tokens=16,
    so_args={"schema_type": "regex", "schema": r"[0-9]{4}"},
)

5디렉토리 구조 해부

위에서 아래로 읽는 순서와, 기능을 찾아갈 지도
DeepInfer/ 저장소 루트 · 커밋 9bd9cf2 ├── README.md 공개 범위·지원 조건·벤치마크 안내 ├── pyproject.toml 패키지 정보·빌드 의존성·품질 도구 설정 ├── requirements*.txt 공통·장치별·개발 의존성 ├── setup.py / build.sh 네이티브 확장 빌드와 의존성 연결 ├── deepinfer/ │ ├── entrypoints/llm.py 사용자가 호출하는 LLM API │ ├── engine/ 인자·엔진 루프·통계·프로파일링 │ ├── worker/ 장치 실행·그래프·캐시 공간 │ ├── hugging_face/ 모델 설정·토크나이저·가중치 로딩 │ ├── model_executor/ │ │ ├── models/ DeepSeek 모델·DFlash·V4 구성 요소 │ │ ├── layers/tilelang_ops/ 공통 연산 인터페이스와 cuda/asc 구현 │ │ ├── input_metadata/ 단계별 텐서 입력과 인덱스 준비 │ │ ├── parallel_utils/ 프로세스 그룹·통신·사용자 버퍼 │ │ └── eplb/ 전문가 복제·재배치 정책 │ ├── structure_output/ 문법 컴파일·매처·토큰 마스크 │ ├── distributed/ 공유 메모리 기반 방송 │ ├── ve/ 이미지 전처리와 비전 입력 연결 │ ├── npu_ops/ NPU 호환·전용 연산 연결 │ └── _C/*.pyi C++ 확장의 Python 타입 선언 ├── csrc/ │ ├── engine/ C++ 요청·스케줄러·블록·출력 관리 │ ├── graph_timer/ 장치 실행 구간 측정 │ └── utils/ 잠금·객체 풀 등 공통 도구 ├── deep_cluster/ 장치 탐지·하드웨어·NUMA 배치 ├── examples/ 오프라인 예제·벤치마크·YoCo 검증 ├── tests/ 엔진·모델·통신·Worker 회귀 검사 ├── eval/ 평가 문제 실행과 채점 도구 ├── scripts/ 외부 연산 빌드·타입 선언 생성·포맷 ├── doc/ 운영 설계 문답과 성능 그래프 └── vendor/ 외부 저장소 6개의 서브모듈 참조

5-1. 입문자에게 권하는 독해 순서

  1. examples/offline_inference.py에서 입력·출력의 형태를 봅니다. 파일을 실행할 필요는 없습니다.
  2. deepinfer/entrypoints/llm.py에서 입력 정규화와 요청 번호, 결과 정렬을 찾습니다.
  3. deepinfer/engine/llm_engine.py의 step()에서 스케줄링과 Worker 호출이 만나는 지점을 표시합니다.
  4. deepinfer/worker/worker.py에서 현재 단계와 이전 단계의 처리가 섞이는 이유를 읽습니다.
  5. 관심에 따라 csrc/engine/scheduler.hpp, deepinfer/model_executor/eplb/policy.py, deepinfer/model_executor/layers/tilelang_ops/norm.py 중 하나로 내려갑니다.

처음부터 deepinfer/model_executor/models/v4_modules/의 모든 수식을 따라가려 하면 데이터가 어디서 와서 어디로 가는지 놓치기 쉽습니다. 처음에는 함수 내부의 수학보다 입력의 모양, 상태를 바꾸는 위치, 결과의 소유자를 먼저 표시하세요.

5-2. 커밋 9bd9cf2의 코드 규모

분류파일 수물리 줄 수
Python .py27054,929줄
C++ .cpp152,425줄
C++ 헤더 .hpp183,484줄
타입 선언 .pyi4819줄
셸 .sh10410줄

git ls-files -z의 추적 경로 중 일반 파일을 확장자별로 나누고 물리 줄 수를 집계한 값입니다. 빈 줄·주석·테스트·예제를 포함하며, 바이너리 이미지·.git·외부 서브모듈 구현은 제외합니다. 확장자 기준 집계이므로 Python 수치에는 TileLang 커널도 들어갑니다. Python과 C++ 본문·헤더의 줄 수를 더하면 60,838줄입니다. 이를 전체 시스템의 순수 알고리즘 줄 수로 해석하지 마세요.

검색 습관
함수의 정의 다음에는 호출자와 검증 코드를 찾기

rebalance_experts_global을 발견했다면 tests/models/test_eplb_policy.py도 읽으세요. 함수 이름 검색 → 입력 텐서 모양 확인 → 결과 사용처 확인 → 테스트의 기대값 확인 순서가 유용합니다. 한 파일의 설명문만 읽는 것보다 계약을 더 정확히 파악할 수 있습니다.

6학습 포인트 (기술별)

이 저장소에서 배운 개념을 작은 프로그램의 설계로 옮기기

6-1. Python: 입력을 한 가지 모양으로 만드는 경계

LLM.generate()는 문자열 하나와 문자열 목록을 모두 받지만 내부에서는 목록으로 다룹니다. _add_request()는 설정을 복사하고 토큰을 np.int32로 맞춥니다. 이렇게 입구에서 형식을 통일하면 내부의 모든 함수가 여러 입력 변형을 반복해서 처리할 필요가 줄어듭니다.

실습 아이디어: 문자열 한 개·목록·토큰 목록이 들어올 때의 분기표를 종이에 그리세요. prompts와 prompt_token_ids의 길이가 다를 때 생기는 오류도 찾습니다. 학습 목표는 문법 암기보다 내부 코드가 가정할 수 있는 조건을 입구에서 만들어 주는 일입니다.

6-2. C++와 바인딩: 잠금·반납·빌린 배열의 계약

BlockManagerMutexAcquire는 생성자에서 잠그고 소멸자에서 풉니다. C++의 RAII는 이런 자원 처리를 객체 수명에 연결하는 기법입니다. Scheduler::_schedule()에는 이전 출력이 빌려 쓰던 벡터를 다음 호출에서 비우고 재사용한다는 설명도 있습니다. Python에서 접근 가능하다고 데이터가 영원히 유효한 것은 아닙니다.

실습 아이디어: clone_states·clone_blocks·zero_states의 생성·소비·초기화 위치를 색깔 세 개로 표시하세요. 빌린 데이터를 오래 보관하고 싶을 때 복사와 수명 연장 중 무엇이 필요한지 설명해 보세요.

6-3. PyTorch: shape뿐 아니라 dtype·stride·장치까지

deepinfer/model_executor/layers/tilelang_ops/norm.py의 _check_vectorized_strides()는 마지막 축이 연속인지와 나머지 stride가 16의 배수인지 검사합니다. 같은 [B, M, d] 모양이라도 메모리에 놓인 간격이 다르면 커널이 요구하는 읽기 방식과 맞지 않을 수 있습니다. FP8 변환 결과는 값뿐 아니라 scale factor의 배치도 계약에 포함합니다.

텐서 독해의 네 질문
Shape · Dtype · Stride · Device
Shape는 각 축의 길이, dtype은 숫자의 저장 형식, stride는 축으로 한 칸 움직일 때 건너뛰는 메모리 간격, device는 데이터가 있는 장치입니다. 큰 표를 같은 크기로 그렸어도, 행 순서로 저장했는지 열 순서로 저장했는지는 다를 수 있습니다.

실습 아이디어: 2×3 배열을 행 순서로 적고 전치한 뷰에서 원소가 어떻게 읽히는지 추적하세요. 이어 norm()이 미리 할당한 out을 받을 수 있는 이유를 생각합니다. 출력 공간을 재사용하면 할당 비용을 줄일 수 있지만, 동시에 사용하는 요청과 겹치지 않게 관리해야 합니다.

6-4. GPU 실행: 빠른 계산 전에 불필요한 동기화 찾기

ModelRunner.execute_main_model()과 execute_sample()에는 forbid_cuda_sync() 범위가 있습니다. 장치의 값을 CPU로 가져오는 .item() 같은 연산은 기다림을 만들 수 있습니다. 비동기 실행 경로에 이런 호출이 무심코 끼어들면 겹쳐 실행하려던 계획이 깨질 수 있습니다.

실습 아이디어: tests/test_cuda_sync_guards.py를 읽고, 허용 범위와 금지 범위가 여러 스레드에서 겹칠 때 무엇을 보장하는지 적습니다. 이 검사는 모든 동기화를 완벽하게 찾는 장치가 아닙니다. 테스트는 동시 허용 범위가 있을 때 일부 금지 보고를 놓치는 절충도 명시합니다.

6-5. 분산 처리: 가장 느린 구성원을 기준으로 생각하기

EPLB의 핵심은 전문가 개수를 똑같이 나누는 일만이 아닙니다. 같은 시점에 바쁜 전문가들을 같은 GPU에 놓으면 다른 GPU가 기다릴 수 있습니다. _batch_greedy_indices()가 과거 여러 단계의 부하 벡터를 보존하는 이유를 여기서 찾을 수 있습니다.

실습 아이디어: 토큰이 몰리는 전문가에 복제본을 추가하는 정책과, 이미 만든 복제본을 GPU에 배치하는 정책을 두 장의 표로 분리하세요. “얼마나 복제할까”와 “어디에 둘까”가 다른 결정임을 설명할 수 있으면 성공입니다.

6-6. 테스트: 빠른지와 올바른지는 따로 검증하기

소스 속 검증확인하는 계약따라 해 볼 사고 실험
tests/models/test_eplb_policy.py양방향 매핑 일치·복제 수·입력 불변·동점 처리작은 전문가 표를 손으로 재배치하고 역매핑 확인
tests/models/test_batch_invariant.py같은 토큰 경로의 배치·단독 실행 결과 비교난수 선택과 수치 오차를 분리해 비교하는 방법 정리
tests/models/test_sampler.pyPIT·KS 검사를 이용한 샘플러 분포 검증문장이 자연스러운 것만으로 분포가 맞다고 할 수 있는지 토론
examples/yoco/mask·compact의 메타데이터 및 출력 동등성계산을 생략해도 보존되어야 할 값의 목록 만들기

최적화를 공부할 때는 무엇이 빨라졌는지와 함께, 무엇이 같아야 하는지를 먼저 적으세요. 여기서 “같다”는 문자열·토큰·확률·통계적 분포 중 무엇인지에 따라 검증 방법이 달라집니다. 표는 테스트가 검사하는 조건을 정리한 것입니다. 검사 항목의 존재와 실제 실행 결과는 구분해야 합니다.

7하드웨어 / 시스템 요구사항

코드 공부에 필요한 환경과 실제 모델 실행 환경은 크게 다릅니다
항목저장소에서 확인한 요구사항초보자의 해석
운영체제README: Linux소스 읽기는 다른 OS에서도 가능. 실제 추론 지원과 혼동하지 않기
PythonREADME: 3.12, 패키지 선언: >=3.12우선 공식 안내의 3.12 조합을 기준으로 읽기
C++ 컴파일러GCC >=13.0, 소스 빌드는 C++20Python만 준비하면 끝나는 구조가 아님
NVIDIASM100 GPU, README: CUDA 13requirements는 cu132 PyTorch를 지정. 임의의 CUDA 조합을 보장하지 않음
HuaweiAscend 950 NPU, CANN 9.2torch-npu와 HCCL, Ascend 커널 경로 필요
모델기본 deepseek-ai/DeepSeek-V4.1-Flash-1017가중치·설정·토크나이저가 맞는 체크포인트 필요
장치 수오프라인 예제에 EP8·EP2/DP8·EP2/CP8 등 구성 제시예시의 장치 수가 보편적인 최소 요구량이라는 뜻은 아님
RAM·VRAM·디스크공통 최소 용량을 숫자로 명시한 요구사항은 찾지 못함가중치·문맥 길이·배치·병렬 구성에 따른 별도 산정 필요

7-1. “VRAM 몇 GB면 되나요?”에 숫자 하나로 답할 수 없는 이유

장치 메모리에는 모델 가중치 외에 KV 캐시, 중간 활성값, 통신 버퍼, 초안 생성 상태, CUDA Graph 관련 공간 등이 들어갑니다. EngineArgs.gpu_memory_utilization의 기본값 0.90은 모델이 GPU 메모리의 90% 크기라는 뜻이 아닙니다. 가중치·활성값·KV 캐시를 위해 확보할 메모리 비율이며, 이 값만으로 특정 장비의 수용 가능성을 판단할 수 없습니다.

WorkerBase.profile_num_available_blocks()는 모델 실행을 프로파일링한 뒤, 메모리 활용 한도에서 PyTorch 최대 할당량과 0 이상으로 보정한 PyTorch 외 할당량을 차감합니다. 상태 저장·복사 버퍼 예약분도 빼고 블록 크기로 나눕니다. 이후 전체 프로세스 그룹에서 블록 수를 평균 내고 짝수로 내림합니다. 실행 가능한 배치 크기는 모델 파일 크기뿐 아니라, 실제 실행 경로의 메모리 사용량으로 결정됩니다.

지원 범위
노트북이나 범용 GPU용 시작 튜토리얼로 받아들이지 마세요

현재 README가 명시한 가속기는 SM100과 Ascend 950입니다. Apple Silicon·CPU 단독·다른 세대 GPU는 README의 지원 대상에 포함되지 않습니다. Linux와 Python을 설치했다는 조건만으로 모델을 실행할 수 있는 것은 아닙니다.

아래 실습은 설치·모델 다운로드·추론 코드 실행 없이 완수하도록 구성했습니다. 실제 성능 재현은 별도의 장비와 검증된 의존성 환경이 준비된 뒤 다룰 주제입니다.

7-2. 네트워크 접근이 생기는 지점도 코드로 확인하기

examples/_config.py의 resolve_model_path()는 경로가 로컬 디렉토리가 아니면 huggingface_hub.snapshot_download()로 모델을 받습니다. 로컬 디렉토리는 config.json이 있는지 확인합니다. DEEPINFER_HF_MODEL_DIR은 기본 모델 이름을 해석할 때 적용되며, 사용자가 따로 전달한 모델 이름까지 무조건 덮어쓰지는 않습니다.

또한 build.sh는 패키지를 설치하고 서브모듈을 가져와 빌드합니다. 모델 이름 해석과 빌드 과정에는 네트워크 접근이 포함될 수 있으므로, 로컬 경로를 읽는 일과 구분해야 합니다. 요구사항 표의 근거는 README와 해당 커밋의 설정·소스입니다.

8직접 해볼 수 있는 실습 과제

설치·GPU·모델 다운로드 없이 소스와 종이만으로 완수하는 다섯 과제

모든 과제는 DeepInfer/ 저장소의 파일을 읽는 방식으로 진행합니다. 답은 별도의 학습 노트에 적으세요. 아래 명령은 텍스트 검색용이며, 추론 코드나 빌드 스크립트를 실행하는 명령이 아닙니다. 명령을 쓰지 않고 편집기의 검색 기능으로 같은 결과를 찾아도 됩니다.

과제 01 · 입문

설정값의 출처를 추적하는 표 만들기

읽을 파일: README.md, deepinfer/environ.py, deepinfer/engine/arg_utils.py, examples/_config.py.

할 일: nextn, ZOS, YoCo truncation, batch invariance의 기본값과 변경 지점을 표로 만드세요. 특히 EnvVar의 기본값만 읽었을 때와 EngineArgs.__post_init__()까지 읽었을 때의 차이를 찾습니다.

완료 기준: nextn은 기본 5, YoCo truncation은 off, batch invariance는 꺼짐이고, ZOS는 엔진 종류에 따라 기본 환경값을 정한다는 사실을 설명합니다. NORMAL·COMPLETION은 기본 켜짐, PROMPT는 기본 꺼짐입니다.

# 저장소 루트에서 문자열만 검색합니다.
rg -n 'DEEPINFER_USE_NEXTN_DECODE|DEEPINFER_ZERO_OVERHEAD_SCHEDULING' \
  deepinfer/environ.py deepinfer/engine/arg_utils.py
rg -n 'default_zero_overhead_scheduling' deepinfer/engine/engine_type.py

추가 질문: 환경변수가 처음 접근할 때 캐시된다면 나중에 os.environ만 바꾸는 것으로 충분할까요? deepinfer/environ.py의 rearm()·rearm_all()과 tests/conftest.py의 _clean_env()를 찾아 이유를 적어 보세요.

과제 02 · 입문

블록 할당 상태를 손으로 계산하기

읽을 파일: csrc/engine/block_manager.hpp의 Blocks, can_allocate_nolock(), pin_block(), free().

할 일: 전체 블록이 8개이고 사용 가능한 빈 블록이 현재 3개라고 가정합니다. 2개·4개·8개를 새로 요구하면 각각 어떤 상태인지 판단하세요. 이어 같은 블록을 두 요청이 참조하는 동안 한 요청이 끝나면 바로 재사용해도 되는지 설명합니다.

완료 기준: 답은 순서대로 OK, LATER, NEVER입니다. 참조 수가 2→1이면 아직 사용 중이고, 1→0일 때 빈 블록 목록으로 돌아간다는 과정을 표로 제출합니다.

과제 03 · 중급

마지막 토큰이 사라지지 않는 비동기 종료 경로 찾기

읽을 파일: deepinfer/entrypoints/llm.py의 _run_engine(), deepinfer/worker/worker.py의 execute_model_step()·flush_inflight_reqs().

할 일: ZOS decode 세 단계를 시간표로 그립니다. 각 단계의 모델 계산, 이전 단계 후처리, 현재 샘플링, prev_step_state 저장 위치를 표시하세요. 새 요청이 없어졌을 때도 마지막 상태를 회수하는 경로를 찾아 연결합니다.

완료 기준: “이번 호출의 결과가 반드시 이번 단계의 계산 결과인 것은 아니다”를 설명하고, flush가 필요한 이유와 RequestOutput.clone()이 필요한 이유를 각각 적습니다. 전자는 남아 있는 작업 회수, 후자는 회수될 원본에서 결과를 보존하는 문제입니다.

과제 04 · 중급

EPLB의 동점 규칙과 시간별 부하 추적하기

읽을 파일: deepinfer/model_executor/eplb/policy.py와 tests/models/test_eplb_policy.py의 test_batch_greedy_objective_and_ties().

할 일: 전문가 6개를 GPU 두 곳에 3개씩 놓습니다. 과거 부하가 아래와 같을 때 합계가 큰 전문가부터 배치하되, 후보 점수가 같으면 작은 rank를 선택하세요. 이 과제는 복제본 추가 없이 기존 전문가의 위치만 정하는 단계입니다.

전문가 번호       0   1   2   3   4   5
과거 단계 A     10   0   0   0   0   0
과거 단계 B      0   6   4   0   0   0

목표 점수 = A에서 가장 바쁜 GPU의 부하
          + B에서 가장 바쁜 GPU의 부하

완료 기준: 물리 슬롯 순서 [0, 1, 3, 2, 4, 5]를 얻습니다. GPU0은 전문가 0·1·3, GPU1은 2·4·5를 갖습니다. 전문가 1을 배치할 때 두 후보 점수가 모두 16이어서 GPU0을 선택하는 이유를 설명하세요.

과제 05 · 고급

벤치마크의 숫자와 결과 보존 조건 감사하기

읽을 파일: examples/README.md, examples/benchmark.py, examples/yoco/README.md, deepinfer/environ.py.

할 일: 가상의 10개 decode 단계가 2초 걸렸고, 매 단계 요청 64개에 nextn=5라고 가정합니다. 전부 채택 가정의 총 처리량과, 요청마다 초안 2개만 채택되고 기본 토큰 1개가 추가된 경우를 비교하세요. 여기서는 GPU 수·CP 정규화를 생략한 전체 토큰 수만 계산합니다.

완료 기준: 전자는 10 × 64 × 6 ÷ 2 = 1,920토큰/초, 후자는 10 × 64 × 3 ÷ 2 = 960토큰/초입니다. 이는 계산 연습용 수치이며 DeepInfer 실측 성능이 아닙니다. 이어 YoCo에서 KEEP_TOKENS >= window_size + MAX_BACKTRACKING_TOKENS가 필요한 이유를 서술합니다.

README의 기본 V4.1 안내는 compact와 KEEP_TOKENS=140입니다. 검증 예제의 window 128과 기본 nextn 5에 따른 최소 backtracking 6을 넣으면 하한은 134입니다. 140은 이 하한을 충족하는 안내값이지 모든 모델에서 통하는 상수가 아닙니다. mask·compact 동등성 검증의 L1도 문서상 장치 한 개가 필요하므로, 이 과제에서는 실행하지 않고 검증 항목을 읽습니다.

9관련 기술 심화 학습 로드맵

6주 동안 함수 하나씩 범위를 넓히는 계획

아래 순서는 장비 구매나 전체 설치를 전제로 하지 않습니다. 매주 소스 두세 개를 읽고 작은 산출물을 남기는 계획입니다. 실행 환경을 갖추기 전에도 데이터 흐름과 보존 조건을 설명하는 능력은 충분히 훈련할 수 있습니다.

주차배울 기초와 읽을 소스완료할 산출물
1주차Python 함수·목록·자료형·예외. deepinfer/entrypoints/llm.py, deepinfer/sampling_params.py입력 정규화 분기표와 잘못된 인자 세 가지. 문자열·토큰·요청 번호의 차이 설명
2주차토큰 생성·KV 캐시·배치의 목적. deepinfer/sequence.py, deepinfer/worker/cache_engine.py요청별 상태와 공유 가능한 상태의 구분표. 가중치와 KV의 차이 설명
3주차C++ enum·vector·RAII·pybind11. csrc/engine/block_manager.hpp, csrc/engine/scheduler.hpp할당 상태 전이도. 빈 블록·예약 블록·참조 수를 손으로 추적한 표
4주차비동기 실행·이벤트·메모리 수명. deepinfer/worker/worker.py, deepinfer/worker/zos_status.py, DeferredRelease세 단계의 시간표와 종료 flush 경로. 결과 복사를 없애려면 필요한 계약 정리
5주차분산 그룹·MoE·탐욕 알고리즘. deepinfer/model_executor/parallel_utils/parallel_state.py, deepinfer/model_executor/eplb/policy.pyDP·CP·EP 비교표와 전문가 배치 예제. 동점 처리의 재현성 설명
6주차커널 융합·수치 형식·검증. deepinfer/model_executor/layers/tilelang_ops/norm.py, deepinfer/model_executor/layers/tilelang_ops/cuda/norm.py, 모델 테스트출력 동등성·배치 불변성·샘플링 분포·성능의 검증 기준을 나눈 한 장짜리 보고서

기초가 약하다면 2주차와 3주차 사이에 배열·참조·동시성 개념을 더 공부하세요. 이미 백엔드를 해 본 독자라면 4주차의 이벤트·풀 수명 관리가 기존 경험과 연결되기 쉽습니다. GPU 경험이 있다면 6주차에서 stride와 scale factor 배치, 커널 실행 구성을 더 깊게 추적할 수 있습니다.

학습 전략

도시 전체 지도를 외우기보다 집에서 학교까지 길 하나를 먼저 익히는 방식입니다. “요청 등록 → 배치 선택 → 계산 → 결과 회수”라는 길이 잡히면, 문법 제약·이미지 입력·초안 검증은 그 길에 새 정거장을 추가하며 이해할 수 있습니다.

이후 실제 장비를 확보했다면 같은 모델·커밋·입력·문맥 길이·병렬 구성·정밀도를 고정한 검증 계획부터 세우세요. 먼저 출력 보존 조건을 확인하고 그다음 측정 구간과 워밍업을 정하는 순서가 좋습니다. 이 문서의 범위는 그 계획을 작성할 만큼 코드를 이해하는 데까지입니다.

10핵심 키워드 사전

소스에서 반복해서 만나는 말들을 쉬운 뜻으로 연결하기
용어쉬운 설명
추론이미 배운 모델로 새 입력의 답을 계산하는 일. 이 저장소의 중심 과제
토큰모델이 읽고 쓰는 번호 단위. 자연어 단어나 글자 수와 꼭 일치하지 않음
Prefill입력 토큰을 읽고 이후 생성에 쓸 내부 상태를 준비하는 단계
Decode이전 상태를 참조하며 출력 토큰을 이어 만드는 단계
배치여러 요청의 계산을 한 묶음으로 처리하는 것. 처리량과 대기 시간 사이에 절충이 생김
KV 캐시어텐션 연산에서 다시 쓸 Key·Value 상태. 모델 가중치나 완성된 답변 문자열의 캐시와 다름
블록 테이블한 요청이 사용하는 실제 KV 블록 번호의 목록. 논리적 문맥과 물리 저장 공간을 연결
MoE여러 전문가 신경망 중 일부를 토큰별로 골라 계산하는 모델 구조
논리·물리 전문가모델이 정의한 전문가는 논리 전문가, 장치에 배치한 그 전문가의 복제본은 물리 전문가
DP · CP · EP요청·문맥·전문가처럼 서로 다른 단위를 나누는 병렬화 방식
EPLB전문가별 부하에 맞춰 복제본 수와 배치를 조정하는 정책
Rank분산 실행에 참여하는 프로세스의 번호. 그룹 안에서 자신의 역할을 식별
All-reduce여러 참여자의 값을 합·최솟값 같은 규칙으로 모으고 결과를 함께 받는 집단 통신
ZOSCPU의 배치·후처리 작업을 장치 실행과 겹치는 비동기 스케줄링 방식
이벤트장치 작업의 특정 지점까지 끝났는지 확인하거나 실행 시간을 재는 표식
객체 풀반복 사용할 객체를 모아 두고 빌려주고 돌려받는 구조. 반납 뒤 원본을 계속 참조하면 위험
CUDA Graph반복되는 장치 작업 흐름을 기록해 재사용하는 방식. 입력 버퍼·메모리 수명 관리가 중요
커널 융합여러 작은 연산을 함께 실행해 중간 메모리 접근과 호출 비용을 줄이는 최적화
BF16 · FP8 · FP4서로 다른 비트 폭의 수치 형식. 저장·연산 효율과 표현 정확도를 함께 고려해야 함
Scale factor낮은 비트 폭으로 저장한 수치의 크기 범위를 해석하는 데 필요한 배율 정보
초안 검증미리 제안한 여러 토큰을 주 모델이 확인하는 생성 방식. 제안 수와 최종 채택 수는 다름
SWA가까운 토큰 범위만 참조하는 슬라이딩 윈도 어텐션(sliding window attention)
YoCo이 저장소에서는 KV 공유 구조와 consumer 층의 제한된 재처리 경로를 이해할 때 만나는 이름
배치 불변성함께 처리되는 다른 요청이 달라져도 같은 입력의 모델 계산 결과를 유지하려는 성질
결정적 샘플링고정된 조건과 난수 시드로 같은 출력 선택을 재현하는 것. 배치 불변성과 별도 조건
구조화 출력생성 토큰의 허용 범위를 문법으로 제한해 JSON·정규식·EBNF 형식을 따르게 하는 것
ABI컴파일된 부품들이 서로 호출하고 데이터를 주고받는 약속. 확장 모듈의 호환성에 영향
NUMACPU와 메모리의 접근 거리가 균일하지 않은 시스템 구조. 장치와 가까운 CPU 배치가 중요
PPL정해진 토큰 경로에 모델이 부여한 확률로 계산하는 예측 불확실성 지표. 이 저장소의 회귀 검사에도 사용

재현 가능한 출력을 원할 때 README는 NVIDIA에서 DEEPINFER_BATCH_INVARIANT=1, DEEPINFER_ENABLE_MTP_VARLEN=0, 고정된 SamplingParams.seq_seed를 함께 안내합니다. 시드를 고정하는 일 하나가 배치 구성·수치 연산·가변 검증 길이의 모든 차이를 해결한다고 생각하지 마세요.

11참고 링크

주장을 확인할 원문과, 다음 학습으로 이어지는 공식 자료

저장소와 소스 독해의 출발점

관련 기술의 공식 학습 자료

현재 상태 (2026-10-23 확인)

항목확인 내용과 근거
스타 / 포크20,308 / 2,186 — 2026-10-23 GitHub 기준
생성일2026-10-16 — 2026-10-23 GitHub 기준
최근 push2026-10-21 — 2026-10-23 GitHub 기준
최근 커밋9bd9cf2, 2026-10-21. DeepEP 갱신과 SSH→HTTPS URL 치환 규칙 제거, PR #157
최신 릴리스없음 (2026-10-23 GitHub 기준). 패키지 선언 버전 0.1.0과 GitHub 릴리스는 별개
주 언어Python — 2026-10-23 GitHub 기준. 실제로 Python·C++·TileLang 연산 경로가 함께 존재
코드 규모Python 270파일·54,929줄, C++ 33파일·5,909줄. 커밋 9bd9cf2 기준, 빈 줄·주석 포함, 서브모듈 구현 제외
타입·빌드 코드.pyi 819줄, 셸 410줄. 주요 언어 집계와 별도
패키지 상태pyproject.toml: 버전 0.1.0, 개발 상태 Beta, Python >=3.12
라이선스Apache-2.0 — 2026-10-23 GitHub 기준 및 저장소 LICENSE
공개 사용 범위README 기준 오프라인 추론. 완성된 온라인 서비스에 필요한 KV 시스템·단계 분리·복제본 부하 분산은 별도
소스 기준커밋 9bd9cf2의 추적 파일·의존성 선언·핵심 구현·테스트 명세. 성능 조건은 README와 예제 문서 기준
쓰기 전에 알아둘 한계
공개 엔진의 기능과 운영 서비스 전체의 능력을 구별하세요

README는 완전한 서비스에 별도의 KV 캐시 시스템, VE/Prefill/Decode 분리, prefill·decode 복제본 부하 분산이 필요하다고 명시합니다. 공개 코드에 CacheEngine과 블록 관리자가 존재하는 것은 이 설명과 모순되지 않습니다. 장치 내부의 실행용 캐시를 관리하는 일과, 요청·엔진 사이에서 캐시를 장기간 저장·전달하는 서비스는 범위가 다릅니다.

운영 설계 문답의 장기 캐시 보관·대규모 클러스터 운영 설명은 배경 자료입니다. 서비스 전체를 구성하려면 README에 명시된 외부 계층을 함께 준비해야 합니다. README 성능 주장, 문서의 벤치마크 환산치, 이 글의 가상 계산 예시는 각각 구분해서 읽어야 합니다.

이 커밋의 지원 모델·장비는 한정되어 있으며 외부 연산 구현은 별도 서브모듈로 관리됩니다. 설치 가능성은 패키지 배포 상태와 플랫폼 환경에, 성능과 정확성은 모델·장비·설정과 검증 조건에 따라 달라집니다.