URL: https://www.youtube.com/watch?v=woIYJYd_etI 날짜: 2026-10-06 채널: t3dotgg 원문 제목: What Is an Inference Engine, Anyway? — Charles Frye, Modal 영상 길이: 59분 58초 원문 업로드일: 2026-10-06
📌 핵심 질문 / 추론 엔진의 진짜 난제는 어디에 있는가
==토큰을 받아 다음 토큰을 내놓는 일 자체는 한두 시간 안에 만들 수 있지만, GPU를 비워 두지 않으면서 좋은 토크노믹스(tokonomics)를 달성하는 시스템으로 만드는 일이 추론 엔진의 본질적인 난제다.==
- 추론 서버(inference server)는 HTTP/gRPC 요청을 외부 표현에서 받아 응답으로 돌려주는 경계이고, 추론 엔진(inference engine)은 토큰화·스케줄링·배치 구성·GPU 실행·디토큰화를 조율하는 핵심 시스템이다.
- 프리필(prefill)과 디코드(decode)는 같은 사용자 요청에서 나오지만 산술 집약도, 지연시간, 메모리 접근 패턴이 달라 사실상 서로 다른 하위 워크로드다.
- 성능의 중심은 모델의 행렬 연산만이 아니라 GPU에 다음 작업을 제때 공급하는 호스트 측 스케줄러, KV 캐시 관리, 배치 구성, CPU-GPU 비동기화에 있다.
- 운영 환경에서는 모델 품질 버그, 토크나이저 버그, 장기 실행에 따른 성능 회귀, 이기종(replica) 간 차이를 모두 관측하고 재현할 수 있어야 한다.
Charles Frye는 AI Engineer Summit의 워크숍에서 10~15분의 질문 시간을 남겨 두고 청중이 손을 들면 즉시 끼어드는 방식으로 진행했다. 청중 다수가 추론 엔진을 이미 알고 있었기 때문에 API 뒤에서 토큰이 어떻게 움직이고 어떤 코드가 GPU를 움직이는지, 그리고 운영 가능한 성능을 어떻게 확보하는지까지 애플리케이션 계층에서 하드웨어 계층으로 내려가며 풀었다.
1. 왜 추론 엔지니어링인가
추론은 학습으로 만들어진 모델을 실제로 돈을 벌게 하는 실행 계층이다.
1.1. 추론 인프라에 커지는 수요
-
인프라 엔지니어링의 가치 상승
- Modal의 Sean Wang은 AI 인프라의 “지루한 부분”, 특히 추론 엔진을 만드는 사람들이 마침내 큰돈을 벌고 있다고 농담 섞인 트윗을 올렸다.
- 연구자가 새 모델을 만드는 일만큼이나 모델을 실제 서비스로 돌리는 계층에 수요가 생겼다.
- 연구소는 대규모 추론을 요구하고, 기업은 자체 스택을 소유하려 하며, 조직들은 인프라 스택을 다시 설계하려 한다.
-
학습과 추론의 경제적 비대칭
- 학습(training)은 대체로 비용 센터(cost center)다.
- 모델 가중치를 직접 판매해서 학습 인프라를 자립적인 사업으로 만드는 일은 지금까지 일반적으로 잘 작동하지 않았다.
- 추론(inference)은 모델이 만들어진 뒤 사용자가 토큰과 컨텍스트를 넣고 새 토큰이나 소프트웨어 결과를 받기 위해 돈을 지불하는 수익 센터(revenue center)다.
- 소수의 파운데이션 모델 제작자가 기반 모델을 만들고, 추론 엔지니어가 이를 배포·최적화·커스터마이즈하는 분업 구조가 형성됐다.
-
학습에도 추론 기술이 스며듦
- 포스트 트레이닝(post-training) 적응은 모델에서 샘플을 생성해야 하므로 추론을 반복 호출한다.
- 따라서 추론 엔진의 속도·메모리·스케줄링 문제는 학습 후반부에도 그대로 나타난다.
1.2. 엔지니어의 놀이터
-
새로운 기술 영역
- 대규모 모델이 등장한 지 여러 해가 지났지만 추론은 여전히 매우 새로운 영역이다.
- 애플리케이션 아키텍처에서 선형대수(linear algebra), GPU 커널, 하드웨어와 전자 수준까지 한 엔지니어가 전체 스택을 가로지를 수 있다.
- 이 폭넓은 범위가 추론 엔지니어링을 “엔지니어의 놀이터”로 만든다.
-
Charles Frye의 배경
- Charles Frye는 AI Engineer Summit이 시작될 때부터 참여했고, 주로 Modal에서 몇 년간 추론을 다뤘다.
- 원래 학습 영역에서 이동해 Modal 플랫폼의 수백~수천 GPU에서 여러 팀의 추론 배포와 최적화를 지원했다.
- 직접 추론 애플리케이션도 만들었으며, 그 사례가 입구에 전시한 작은 인터랙티브 아트 작품이다.
-
모델이 만든 미술관 안내문
- 작품은 카메라가 보는 것을 비전-언어 모델(vision-language model)에 통과시킨다.
- Qwen 계열 모델을 SGLang 추론 엔진으로 서빙하고 Modal에서 실행한다.
- 모델은 입력을 미술 작품처럼 묘사해 작은 미술관 플래카드(placard)를 생성한다.
- “누군가 작품을 설명하는 작은 플래카드를 써 줘야 비로소 예술이 된다”는 농담이 붙었다.
- 입구로 들어오는 선을 가리키자 모델이 귀여운 설명을 생성했다.
- 이 애플리케이션은 최저 지연시간형과 최고 처리량형 사이에 놓인 추론 워크로드의 한 예다.
2. 추론 워크로드의 세 가지 모양
사용자와 시스템의 상호작용 정도, 입력·출력 길이, 허용 지연시간, 접두사 재사용률에 따라 같은 모델도 전혀 다른 엔진 부담을 만든다.
2.1. Chatbot-plus
-
사람과 외부 도구를 함께 상대하는 대화형 시스템
- ChatGPT나 Claude Code 같은 시스템에는 사람이 기다리며 추가 컨텍스트를 제공한다.
- “plus”는 사람과 대화하는 것만이 아니라 툴 호출(tool call)로 외부 시스템과 상호작용한다는 뜻이다.
- 응답은 대체로 수십~수백 토큰의 짧은 디코드다.
- 사용자는 수백 밀리초 안에 무언가가 나오기를 기대하며, 오래 기다리면 지루해지고 화를 내고 떠난다.
- 대화 이력이나 시스템 프롬프트 때문에 접두사 재사용률(prefix reuse)이 높다.
-
핵심 성능 목표
- 짧은 출력과 높은 상호작용성 때문에 첫 토큰까지 시간(time to first token, TTFT)과 토큰 사이 지연(inter-token latency)이 중요하다.
- 처리량보다 체감 응답성이 우선이며, 대기열을 길게 만들면 사용자 경험이 바로 무너진다.
2.2. 백그라운드 에이전트
-
사람의 즉시 응답 밖에서 실행되는 작업
- 백그라운드 에이전트는 Claude Code와 비슷한 작업을 하지만 사람의 다음 입력에 직접 응답하지 않고 뒤에서 실행된다.
- Devin, Ramp Inspect, OpenClaw, 코딩이 아닌 사례의 Herbie 같은 시스템이 예다.
- 툴 호출과 외부 시스템 조작이라는 비슷한 능력을 갖지만 성능 프로파일은 Chatbot-plus와 다르다.
-
지연시간 예산의 변화
- 좋은 엔지니어가 만들 법한 품질로 풀 리퀘스트(PR)를 만들 수 있다면 몇 분의 여유가 있다.
- 작업 품질에 몇 시간이 허용될 수도 있으므로 네트워크 오버헤드 수 밀리초를 줄이는 일이 대화형 서비스만큼 절박하지 않다.
- 높은 접두사 재사용률은 유지되지만 처리량과 비용 효율을 함께 보게 된다.
2.3. 데이터 프로세서
-
비정형 데이터를 구조화하는 파이프라인
- PDF 같은 비정형 데이터를 받아 데이터베이스에 넣을 구조화된 객체를 추출한다.
- Reducto는 문서 처리 플랫폼의 사례이고, Fathom은 동영상에서 트랜스크립트를 뽑는 사례다.
- 시스템 프롬프트가 있을 수 있지만 입력 문서에 비해 작고, 문서마다 달라 접두사 재사용률은 낮다.
- 입력은 길고 출력은 입력보다 짧은 구조화 객체인 경우가 많다.
-
처리량 중심의 운용
- 각 요청의 지연시간보다 데이터베이스 백필처럼 많은 문서를 한꺼번에 처리하는 aggregate throughput이 중요하다.
- 출력 디코드는 짧고, 대규모 동시 요청을 GPU에서 효율적으로 묶는 일이 핵심이다.
3. 한 요청의 생명주기와 측정 지표
클라우드 추론을 기준으로 요청은 전처리된 입력을 프리필하고, 여러 디코드 실행으로 출력 토큰을 만든 뒤 사용자나 툴에 돌려준다. 미래에는 추론 엔진이 개인 컴퓨터에서도 더 많이 실행될 수 있다.
3.1. 프리필과 디코드
-
프리필 단계
- 클라이언트가 토큰을 서버로 보낸다.
- 프리필(prefill)은 입력 토큰 전체를 모델의 한 번의 forward pass로 처리한다.
- 계산 결과 중 이후 토큰 생성에 필요한 중간 상태를 KV 캐시(Key-Value cache)에 저장한다.
-
디코드 단계
- 디코드(decode)는 한 번에 한 토큰 또는 몇 토큰씩 여러 번 forward pass를 실행한다.
- 생성이 끝나면 출력 토큰을 사용자에게 돌려주거나, 툴 호출을 만들어 외부 시스템과 상호작용한다.
- 프리필과 디코드는 한 요청에서 이어지지만 서로 다른 코드 경로와 자원 패턴을 가진다.
-
청중의 화면 밝기 질문
- 청중이 화면 크기와 밝기 조절을 물었고, Charles Frye는 어두운 모드 슬라이드를 만든 대가라며 밝기를 고칠 수 있을지 모르겠다고 답했다.
- 그는 곧바로 추론 구조로 돌아가면서 질문을 계속 환영했다.
3.2. 운영자가 봐야 할 네 가지 축
-
요청률과 복제본 처리량
- 외부 사용자의 aggregate queries per second(QPS)는 통제하기 어렵다.
- 엔진 단위에서는 replica 하나가 처리할 수 있는 QPS를 측정하고, 사용자 수요와 비교한다.
- 입력·출력 토큰 수는 각각 프리필·디코드 부담을 결정한다.
-
토큰 길이와 비결정성
- 입력 토큰 수는 사용자 컨텍스트가 결정한다.
- 출력 토큰 수는 사용자가 정하는 동시에 모델이 언제 멈출지 결정하므로 완전히 결정론적이지 않다.
- 두 길이 모두 실제 워크로드를 측정하고 벤치마크해야 한다.
-
KV 캐시 재사용
- 프리필에서 만든 중간 산출물을 KV 캐시에 넣는다.
- 캐시가 얼마나 재사용되는지가 워크로드 정의의 핵심 요소다.
- 사용자 입력이 주도하지만 에이전트 시스템의 고정 시스템 프롬프트처럼 재사용 패턴이 비교적 일정한 경우도 있다.
-
지연시간 SLO
- 애플리케이션 계층은 첫 토큰을 얼마나 빨리 받을지와 출력 토큰을 얼마나 빠르게 이어 받을지 정한다.
- TTFT는 프리필이 끝나 첫 출력 토큰을 보낼 때까지의 시간이다.
- time per output token 또는 inter-token latency는 디코드 중 토큰 사이 간격이다.
- 이 SLO가 엔진을 어떻게 배치하고 성공을 어떻게 측정할지 결정하는 주된 제약이다.
3.3. 애플리케이션과 엔진 사이의 두 하위 워크로드
-
프리필과 디코드의 비대칭
- 프리필은 긴 입력에 대해 높은 산술 집약도(arithmetic intensity)로 많은 계산을 한다.
- 디코드는 사용자별로 훨씬 적은 연산을 하며, 모델 파라미터와 KV 상태를 반복적으로 읽는 비중이 크다.
- 한쪽은 입력 처리량, 다른 한쪽은 반복 생성 지연을 최적화하므로 엔진 내부에서 반독립적으로 운영된다.
-
엔진 설계의 기본 제약
- 프리필과 디코드는 큐 구성, 배치 크기, GPU 메모리 사용, 스케줄링 정책에서 다른 선택을 요구한다.
- 단일 애플리케이션 요청이더라도 엔진을 내려다보면 프리필 하위 워크로드와 디코드 하위 워크로드로 갈라진다.
4. 추론 서버와 추론 엔진의 구조
추론 서버는 외부 계약을 지키고, 추론 엔진은 GPU를 향한 내부 실행을 극도로 빠르게 만든다.
4.1. 서버와 엔진의 구분
-
추론 서버(inference server)
- HTTP 또는 gRPC 요청을 받고 HTTP 응답으로 돌려주는 입출력 경계를 담당한다.
- 유니코드 문자열, PNG 이미지, MP4 동영상, WebRTC 스트림 같은 사람이 이해하는 표현을 받는다.
- 서버 계층에서 HTTP가 병목인 프록시와 달리, 추론 복제본은 대체로 수십·수백·많아도 수천 QPS를 처리하므로 범용 하드웨어가 입출력만으로는 쉽게 포화되지 않는다.
-
추론 엔진(inference engine)
- 외부 입력을 토큰 컬렉션으로 전처리하고 GPU 텐서로 매핑한다.
- 모델이 K개 입력을 K+1번째 토큰에 대한 예측 텐서로 바꾸도록 실행한다.
- 결과 텐서를 토큰 공간과 사용자 친화적인 표현으로 되돌리는 디토큰화(post-processing)를 담당한다.
- 진짜 성능과 복잡성이 있는 곳은 일반적인 HTTP 서빙보다 이 내부 계층이다.
-
vLLM의 위치에 대한 Q&A
- 청중은 추론 서버·엔진의 차이와 vLLM이 어디에 놓이는지 물었다.
- Charles Frye는 vLLM이 HTTP/gRPC 서버로 동작하면서 엔진 계층도 함께 제공한다고 답했다.
- 일반적인 배포는 단일 요청을 받아 단일 응답을 돌려주는 서버 인터페이스로 보이지만, 그 안쪽에 엔진 구성요소가 있다.
4.2. 통신 프로세스의 네 층
-
서버 I/O 및 전처리
- 서버 I/O 프로세스는 외부 세계와 통신한다.
- 토크나이저(tokenizer)가 문자열이나 멀티모달 입력을 토큰으로 바꾸고, 디토크나이저(detokenizer)가 생성 토큰을 응답으로 되돌린다.
- SGLang과 vLLM의 구현 세부는 다르지만 이 경계의 역할은 비슷하다.
-
스케줄러 프로세스
- 스케줄러는 큐를 관리하고 GPU에 어떤 작업을 언제 보낼지 정의한다.
- 요청별 자원 소비량과 현재 가용 자원을 판단해 모델 러너에 전달할 배치를 만든다.
- SGLang 구조에서 설명한 스케줄러 프로세스가 핵심 실행 제어점이다.
-
모델 러너(model runner)
- 하나 이상의 GPU 밀착 프로세스가 실제 모델 추론을 실행한다.
- PyTorch와 커널 라이브러리를 통해 가속기에 작업을 제출하며, 네트워크 카드에 비동기 작업을 맡기는 웹 서버의 방식과 비슷하다.
- GPU에 올라가는 모델 forward pass가 대부분의 FLOP와 비용을 차지한다.
-
성능의 두 중심
- GPU는 가장 비싸고 초당 페타플롭급 연산을 수행할 수 있는 부품이므로 마이크로초 단위 최적화가 집중된다.
- 그러나 GPU가 무엇을 할지 정하는 스케줄러가 GPU의 게이트키퍼다.
- GPU를 충분히 바쁘게 만들지 못하는 스케줄러가 실제 병목이 될 수 있다.
4.3. 상태성, 토크나이저, 디토크나이저에 대한 Q&A
-
성능을 무시하면 무상태, 성능을 원하면 상태성
- 청중이 추론 워크로드가 상태 저장인지 무상태인지 물었다.
- 성능을 신경 쓰지 않으면 무상태(stateless)로 취급할 수 있지만, 실제 대부분의 경우에는 상태가 있다.
- 가장 중요한 상태는 이전 요청에서 계산한 KV 캐시이며, 특정 세션 개념과 연결된다.
- 개별 엔진 복제본은 KV 캐시를 추적할 수 있지만 세션의 의미를 정의하는 일은 보통 엔진 바깥 래퍼가 맡는다.
- NVIDIA Dynamo나 LMDeploy 같은 계층이 세션을 정의하고, 클라이언트가 그 아키텍처에서 세션을 사실상 규정한다.
-
토크나이저와 디토크나이저의 연결
- SGLang에서는 두 요소가 직접 통신하지 않는 것으로 보이며, vLLM에서는 같은 엔진 매니저 프로세스 안에 있을 수 있다.
- 둘은 서로 메시지를 주고받기보다 입력을 토큰으로, 토큰을 출력으로 매핑하는 동일한 기반 라이브러리와 규칙을 사용한다.
- Hugging Face tokenizers 같은 하부 라이브러리를 공유하면 모호한 입력에도 같은 결정을 내릴 수 있다.
- 토큰화가 디토큰화보다 구현상 더 어렵고, 디토큰화는 구현자가 통제하는 부분이 더 크다.
-
긴 입력이 첫 토큰을 늦추는 이유
- 토크나이저가 병렬화되어 여러 프로세스로 실행돼도 첫 출력 토큰의 TTFT는 길어진다.
- 핵심 원인은 토큰화가 아니라 모델 코어 루프가 긴 입력을 처리해야 하기 때문이다.
- 충분히 큰 구간에서는 10,000토큰보다 100,000토큰을 처리하는 데 대략 10배의 시간이 걸리는 선형 관계가 나타난다.
- 입력을 여러 배치로 쪼개면 각 조각에 큐 대기와 혼잡이 반복되어 긴 배치의 지연이 더 커질 수 있다.
- “첫 토큰 생성”은 토큰화 완료가 아니라 모델이 첫 출력 토큰을 만든 시점을 뜻한다.
-
입력과 출력 속도 차이
- SGLang 계열에서는 디토크나이저 프로세스가 여러 개이고 토크나이저는 하나인 구성이 가능하다.
- 입력 토큰은 프리필에서 훨씬 빠른 총 토큰/초로 처리되고, 출력 토큰은 디코드 속도가 낮다.
- 디토큰화가 사용자 응답의 마지막 경계가 될 수는 있지만 모델 forward pass라는 핵심 자원의 병목은 아니어서 hot path에서 조금 벗어난다.
- 출력 1,000토큰/초라면 토큰당 평균 약 1ms이고, 낮은 디코드 처리량이나 대형 모델에서는 10~20ms 이상도 될 수 있다.
- 토크나이저 자체는 보통 밀리초 이하이며 요청마다 한 번 실행된다. 토크나이저 캐시도 가능하지만 KV 캐시만큼 논의되지 않는다.
- 대략 200억(20B) 파라미터 이상 모델에서는 일반 토크나이저가 병목으로 드러나지 않는 경우가 많다. 작은 모델에 매우 긴 컨텍스트를 넣을 때는 토크나이저가 병목이 될 수 있다.
4.4. 왜 여러 프로세스와 Python을 쓰는가
-
각 구성요소에 독립적인 제어 흐름 부여
- 서버 I/O, 토큰화·디토큰화, 각 모델 러너를 별도의 제어 흐름으로 분리한다.
- 토크나이저와 디토크나이저는 일반 웹 서버보다 계산량이 많고, 모델 러너는 GPU에 비동기 작업을 제출하므로 각자의 이벤트 루프가 유리하다.
- 서로 통신해야 할 양이 충분히 작아 같은 스레드에 억지로 넣을 이유가 적다.
-
Python 스레드보다 프로세스를 택하는 이유
- 전통적으로 Python은 프로세스마다 한 스레드만 제대로 병렬 실행하며, 글로벌 인터프리터 락(GIL)이 같은 프로세스의 스레드를 막는다.
- 최근 변화가 시작됐지만 호환성과 성능을 위한 작업이 여전히 남아 있다.
- 프로세스를 나누면 각 구성요소가 GIL의 간섭을 덜 받는다.
-
Python이 계속 남는 이유
- 연구자에게 사용하기 쉽고, 모델이 연구·데이터 사이언스 환경에서 계속 나온다.
- Python은 C·C++ 상호운용을 핵심 설계 원칙으로 깊게 유지해 가속기와 컴파일된 코드에 연결하기 쉽다.
- JavaScript처럼 비슷하게 편한 언어보다 GPU 가속 코드와 소통하는 경로가 깊고 널리 마련돼 있다.
-
Rust 재작성의 적절한 표적
- GPU에서 실행되는 코드는 이미 컴파일 언어로 거의 한계까지 최적화된다.
- 모델 워커는 GPU에 할 일을 조직하는 역할이므로 Rust로 다시 쓴다고 큰 이득이 보장되지 않는다.
- 반면 호스트 측 스케줄러는 적은 GPU 자원을 조작하고 모델·PyTorch 세부를 모두 알 필요가 없는 얇은 계층이다.
- 스케줄러가 GPU 작업보다 빨라야 한다는 압력이 GPU가 빨라지고 GPU 작업량이 줄수록 커진다.
- 스케줄러는 엔진별 호스트 코드로 비교적 얇게 다시 쓸 수 있어 향후 Rust 재작성의 좋은 후보가 된다.
- 여러 스케줄러를 병렬로 돌리면 GPU 자원 락과 조정 복잡성이 커진다. 스케줄러를 마이크로초까지 줄여도 이전 GPU 작업이 끝날 때까지 새 작업이 시작되지 않으므로 수십~수백 밀리초의 실제 GPU 작업에 비해 이득이 작다.
4.5. 요청 생명주기와 동적 배칭
-
입력에서 모델 러너까지
- 서버가 외부 입력을 받는다.
- 토크나이저가 전처리한 요청을 스케줄러에 보낸다.
- 스케줄러가 자원 소비량과 가용 자원을 계산한다.
- 모델 러너에 넣을 요청 배치를 구성한다.
-
배칭의 이유
- GPU와 TPU는 여러 요청을 병렬로 실행할 때 높은 효율을 얻는다.
- 데이터베이스에서 같은 테이블을 순차 스캔할 쿼리 서너 개를 한 번에 읽는 것처럼, 비싼 데이터 로딩과 실행을 여러 요청에 나눠 부담한다.
- 모델 러너는 반복적으로 배치를 시작하고 토큰과 토큰 확률 분포인 로짓(logits)을 내놓는다.
- 생성된 토큰은 디토크나이저로 흘러가 외부 세계가 읽을 수 있는 응답이 되어 서버로 돌아간다.
-
토크나이저와 디토크나이저의 직접 통신 여부
- 두 구성요소는 일반적으로 서로 직접 통신할 필요가 없다.
- 청중이 토큰화와 디토큰화의 일관성을 물었고, Charles Frye는 같은 기반 라이브러리가 같은 결정을 보장하므로 직접 통신이 필요하지 않다고 조심스럽게 답했다.
- 시스템은 입력 토큰과 출력 토큰의 매핑 규칙을 공유하는 쪽에 의존한다.
5. GPU 내부의 모델 실행과 엔진별 특수성
추론 엔진의 차이는 GPU의 원시 성능보다 GPU를 얼마나 방해하지 않고 계속 일하게 만드는지에서 크게 갈린다.
5.1. 커널과 모델 forward pass
-
커널은 외부 라이브러리에서 온다
- 엔진은 모든 연산을 직접 구현하지 않고 백엔드가 제공하는 커널(kernel)을 소비한다.
- 유용하고 널리 쓰이는 커널은 결국 공용 커널 라이브러리에 들어간다.
- 엔진마다 원시 GPU 성능이 크게 다르지 않은 이유도 공통 라이브러리를 공유하기 때문이다.
- 트리 기반 speculative decoding에 쓰이는 tree attention처럼 엔진별 특수 커널도 있지만, 인기가 높아지면 라이브러리로 분리된다.
-
모델별 forward pass
- 모델 forward pass 코드는 어떤 커널을 선택하고 어떤 순서로 호출할지 제어한다.
- 새 모델 아키텍처를 추가하려면 각 엔진에 모델별 구현이 필요하다.
- Hugging Face Transformers의 참조 구현은 정확성 기준으로는 유용하지만 충분히 최적화되지 않은 경우가 많다.
- SGLang과 vLLM에는 Transformers 구현을 가져와 약간 수술하고 자동 커널 융합·최적화·재작성을 시도하는 경로가 생겼지만, 많은 모델은 여전히 엔진별 손작성 코드가 필요하다.
-
배치 구성의 특수 소스
- 모델 forward pass를 감싸는 배치 구성(batch construction)이 엔진별 차별화의 핵심이다.
- 프리필 큐와 디코드 큐를 따로 둘지, 한 큐에서 섞을지 선택할 수 있다.
- 순수 프리필, 순수 디코드, 혼합 실행을 동적으로 바꾸면 워크로드에 따라 성능이 달라진다.
- 이상적인 추론 서버는 대기열이 자라지 않고 가능한 즉시 비워야 한다.
- 큐를 완전히 없애기 어렵더라도 계속 커지는 큐는 실패 신호로 봐야 한다.
5.2. 토큰화에서 멀티모달 전처리까지
-
텍스트 토큰화는 성숙한 영역
- 일반 문자열의 유니코드 바이트를 토큰으로 바꾸는 문제는 기존 라이브러리로 대부분 해결됐다.
- 성능 최적화의 새 기회는 멀티모달 입력·출력에서 더 많이 나타난다.
-
이미지·동영상 토큰화
- 이미지 토큰화는 유니코드 문자열보다 어렵고, 입력을 텐서로 만드는 전처리 경로가 길다.
- 동영상은 FFmpeg로 원시 프레임을 추출한 뒤 텐서로 변환해 모델에 넣을 수 있다.
- 멀티모달 오픈 웨이트 모델은 좋아졌지만 실제 trace를 보면 이 경로에는 여전히 최적화 여지가 많다.
5.3. 모델 계층의 두 가지 커널 부류
-
토큰 간 계산과 토큰별 계산
- 현대 언어 모델은 입력 시퀀스에 대해 토큰 간 계산을 수행하고, 각 토큰을 풍부하게 만드는 토큰별 계산을 수행한 뒤 표현을 합쳐 다음 레이어로 넘긴다.
- 이 패턴은 레이어마다 반복된다.
- 토큰 간 계산은 어텐션(attention) 또는 선형 어텐션(linear attention)이고, 토큰별 계산은 MLP다.
-
어텐션 백엔드
- FlashAttention 계열 구현과 FlashInfer, NVIDIA의 CUTLASS, OpenAI의 Triton 구현이 대표적이다.
- TensorRT-LLM도 어텐션 커널을 백엔드로 제공한다.
- 어텐션에 쓰이는 이름들이 MLP의 행렬 곱에도 백엔드로 반복해서 나타난다.
-
Dense MLP와 Mixture of Experts
- Dense MLP는 모든 토큰이 같은 네트워크를 통과하는 고전적인 신경망이다.
- Mixture of Experts(MoE)는 토큰마다 일부 전문가 네트워크만 선택해 보낸다.
- Dense MLP에는 DeepSeek의 DeepGEMM이 SGLang에서 기본처럼 널리 쓰인다.
- vLLM에는 양자화에 초점을 둔 Marlin과 bitsandbytes 백엔드가 있다.
- MoE는 토큰을 어느 전문가로 보낼지 라우팅하고 결과를 다시 모으는 통신 문제가 추가된다.
- DeepSeek의 DeepEP 같은 all-to-all 통신·라우팅 커널을 행렬 곱과 분리할 수 있지만, 분리에는 성능 페널티가 생길 수 있다.
- DeepSeek-V4에서는 라우팅과 행렬 곱을 하나의 거대한 메가 커널(mega-kernel)로 합치는 접근이 제시됐다.
-
엔진 설정 방식
- SGLang은 시작 시 구성과 스마트 기본값을 비교적 전면에 드러낸다.
- vLLM은 스마트 기본값을 더 많이 사용하고 환경 변수로 세부 동작을 바꾸는 쪽에 가깝다.
- 두 프로젝트의 설정과 구현은 며칠 단위로 빠르게 바뀌므로 실제 배포 시 버전을 확인해야 한다.
6. 스케줄링·캐시·병렬화의 핵심 문제
6.1. 동시성, KV 캐시 우선순위, 캐시 스래싱
-
많은 요청을 동시에 다루는 위치
- 청중은 매우 많은 요청이 들어올 때 동시성을 누가 결정하는지 물었다.
- 답은 커널이나 백엔드가 아니라 배치 구성과 스케줄러 계층이다.
- 스케줄러는 KV 캐시가 이미 할당된 요청을 일반적으로 우선한다.
- 캐시를 재사용하면 입력을 다시 계산하지 않아도 되므로 GPU 일을 줄일 수 있다.
-
캐시 축출과 디스크
- 공간이 부족해 캐시를 축출하면 CPU 메모리로 보내고, 더 밀리면 디스크로 보낼 수 있다.
- 이는 운영체제의 스왑(swap)과 비슷하다.
- MacBook이 메모리를 디스크로 스왑하기 시작하면 사용할 수 없을 정도로 느려지는 것처럼, KV 캐시 스래싱(thrashing)은 엔진이 잘못 배치됐다는 신호다.
- CPU·디스크 축출은 완전 중단을 피하기 위한 안전장치로는 유용하지만 정상적인 성능 상태로 보면 안 된다.
-
서버리스와 콜드 스타트 Q&A
- 청중은 서버리스 배포와 콜드 스타트를 물었다.
- Charles Frye는 발표가 벤더 토크가 되지 않기로 약속했다며 세부 설명을 줄였다.
- Modal의 “Truly Serverless GPUs” 글에서 메모리 스냅샷, GPU 메모리 스냅샷, 커스텀 파일 시스템 등 여러 조각으로 콜드 스타트를 줄이는 방법을 확인할 수 있다고 안내했다.
6.2. KV 캐시와 접두사 공유
-
어텐션의 계산·저장 절충
- 핵심 어텐션 계산은 기본적으로 시퀀스 길이에 대해 이차적(quadratic)이다.
- 이미 계산한 값을 저장하면 계산 복잡도를 선형으로 바꾸는 대신 저장 공간을 선형으로 사용한다.
- GPU 밖에 저장했다가 다시 읽는 일이 재계산보다 느릴 수 있으므로 GPU 메모리를 효율적으로 써야 한다.
-
접두사 공유
- “Thou shalt not”으로 시작하는 여러 문장을 생각하면 공통 접두사까지의 계산을 한 번만 수행할 수 있다.
- 토큰 하나가 달라지는 순간 그 뒤의 계산은 공유할 수 없다.
- 공유 구조는 트리 또는 trie 형태가 된다.
- 수만 토큰의 거대한 시스템 프롬프트를 가진 에이전트라면 여러 사용자 사이에서 이 접두사를 공유하는 가치가 특히 크다.
-
Paged·Radix KV 캐시
- 페이지 또는 radix 방식의 KV 캐시는 운영체제의 페이지 캐시와 비슷한 자료구조에 상태를 저장한다.
- 어텐션 커널에 넘길 텐서를 실행 시점에 재구성한다.
- 과거에는 엔진이 페이지 KV 캐시의 핵심 문제를 직접 해결했지만, 최신 FlashAttention 계열 커널이 페이지 레이아웃과 재구성 일부를 흡수했다.
- 이제 엔진의 핵심 책임은 KV 캐시 용량 관리와 레이아웃 배치에 더 가깝다.
- Charles Frye가 언급한 팀의 FlashAttention 4 작업과 radix형 KV 캐시가 이런 이동을 보여준다.
6.3. CPU-GPU 비동기성과 CUDA Graph
-
GPU를 항상 바쁘게 만들기
- 모델 수준과 엔진 수준 모두에서 GPU의 어느 순간에도 커널이 실행되도록 해야 한다.
- CPU는 다음 GPU 작업을 결정하되 진행을 막아서는 안 된다.
- GPU가 직접 HTTP 서버를 실행해 사용자에게 응답할 수는 없으므로 CPU 작업 자체는 필요하지만, 동기화로 GPU를 멈추게 하면 안 된다.
-
호스트-디바이스 동기화의 위험
- CPU와 GPU 사이에는 결과와 포인터 정보가 전달돼야 한다.
- 실수로 host-device sync를 넣으면 CPU가 GPU 완료를 기다리며 전체 파이프라인을 막는다.
- 성능 엔지니어링의 목표는 CPU 제어 작업과 GPU 커널이 서로 겹쳐 실행되도록 만드는 것이다.
-
CUDA capture와 CUDA Graph
- 모델 forward pass에서 실행되는 커널들을 CUDA capture로 추적한다.
- 커널 실행 순서와 특정 포인터의 데이터를 변경하는 관계를 하나의 DAG로 만든다.
- 이 CUDA Graph는 매 커널마다 CPU가 실행할 것과 포인터를 다시 결정하는 비용을, 어떤 그래프를 시작할지 정하는 한 번의 CPU 작업으로 줄인다.
- GPU는 그래프에 포함된 전체 커널을 실행하고, CPU는 그래프 선택만 담당한다.
- 모델 forward pass 내부의 세부 구현을 매번 CPU가 간섭하지 않아도 된다.
6.4. 디코드의 순차성·추측 디코딩
-
디코드의 메모리 대역폭 문제
- 디코드는 순차적이므로 매 토큰마다 모델의 전체 파라미터 또는 MoE의 활성 파라미터를 읽어야 한다.
- 사용자를 대신해 토큰 하나마다 1TB 또는 100GB의 데이터를 읽으면서 몇 밀리초마다 토큰을 생성하는 상황이 생긴다.
- 필요한 메모리 대역폭이 페타바이트/초 규모가 되어 일반적인 GPU 실행만으로 달성하기 어렵다.
-
Speculative decoding
- 별도 작은 모델인 speculator가 다음 몇 토큰을 먼저 추측한다.
- 대상 모델은 그 후보들을 병렬로 평가하고, rejection sampling 같은 올바른 샘플링을 적용한다.
- 이 방식은 순차 실행과 수치적으로 같은 출력을 보장하면서 여러 디코드 단계를 병렬화한다.
- 순차적인 디코드를 작은 프리필처럼 바꾸는 효과가 있다.
-
속도 향상의 성격
- Speculator가 한 번에 맞히는 연속 토큰 수가 늘면 디코드 처리량은 대략 선형으로 증가한다.
- 일반적인 엔진 최적화는 1%, 5%, 10%를 한 번씩 얻는 “인치 게임”이라 매 퍼센트포인트마다 어려운 성능 작업이 필요하다.
- 더 좋은 speculator를 학습하면 데이터와 계산을 투입한 뒤 기준선 대비 2배, 4배, 8배의 속도 향상도 가능하다.
- 이 기법은 LPU나 Cerebras 같은 새로운 가속기로 바꾸지 않고도 대형 모델을 NVIDIA 하드웨어에서 약 1,000토큰/초 수준으로 실행하는 데 중요한 역할을 한다.
-
병렬화에서 남는 문제
- 가속기 여러 장으로 작업을 나누는 병렬화 기법은 많지만 발표 시간 때문에 세부 슬라이드는 건너뛰었다.
- 좋은 커널이 병렬 실행을 지원해야 하고, 엔진의 모델 forward pass 코드가 장치 간 통신을 조정해야 한다.
- 실제 문제의 상당 부분은 연산 자체보다 통신에서 발생한다.
7. 관측 가능성과 운영 디버깅
추론 서비스를 배포하면 애플리케이션의 오류와 엔진의 정확성·성능 오류가 서로 다른 원인으로 나타나므로 로그와 trace를 충분히 남겨야 한다.
7.1. 세 종류의 버그
-
애플리케이션 수준 버그
- 모델이 이상하게 행동하는 문제는 애플리케이션 개발자의 책임일 수 있다.
- 원인이 엔진에 없어도 운영 대시보드에는 모델의 이상 행동으로 나타난다.
-
모델 품질·정확성 버그
- 엔진이 추론을 실제로 올바르게 수행하는지 확인해야 한다.
- 성능 최적화가 모델 행동을 바꾸지 않았는지 보장해야 한다.
- 새 모델이 출시될 때 토크나이저가 토큰화와 채팅 템플릿을 조금씩 잘못 처리하는 일이 흔하다.
- 이런 버그는 모델 출시 뒤 몇 주 동안 정리되지만 엔진 운영자는 항상 경계해야 한다.
-
성능 버그
- 한 복제본을 장시간 실행했을 때만 성능이 떨어지는 회귀가 생길 수 있다.
- 이기종 클라우드 환경에서는 같은 설정의 복제본끼리도 성능이 다를 수 있다.
- GPU 세대, NUMA 배치, 런타임 상태가 다른지 조사해야 한다.
7.2. 배포 전후의 로그와 평가
-
로그만으로 디버깅 가능한 수준
- 충분한 정보를 로그에 남기면 개발 서버를 새로 띄우고 문제를 재현하는 시간을 줄일 수 있다.
- 애플리케이션 입력부터 모델 품질과 엔진 실행까지 추적 가능한 연결고리가 필요하다.
-
배포 전 모델 평가
- SGLang·vLLM에 있는 스크립트와 외부 벤치마킹 도구로 실제 배포 대상을 평가한다.
- 추론 엔진을 바꿀 때 모델 품질 평가와 성능 벤치마크를 함께 돌린다.
- 수치를 계산하고 trace를 저장해 나중에 회귀 원인을 비교할 수 있게 한다.
-
토크나이저 디버깅 팁
- 토크나이저 버그는 사람이 읽는 문자열만으로 찾기 어렵다.
- 엔진이 토큰 ID도 로그하도록 설정하면 채팅 템플릿과 토큰 경계의 차이를 직접 비교할 수 있다.
-
성능 지표는 과할 정도로 기록
- 성능 버그는 어느 계층에서든 나타날 수 있다.
- 필요해 보이는 것보다 많은 메트릭을 남겨야 한다.
- 나중에 어떤 교차 상관관계가 버그를 즉시 드러낼지 미리 알 수 없다.
7.3. Modal 엔드포인트 대시보드 사례
-
트래픽 급증의 연쇄 효과
- Charles Frye는 앞서 보여 준 아트 프로젝트를 세 복제본으로 띄워 부하 증가를 관찰했다.
- 트래픽 스파이크가 생기면 프리필 쪽에서 큐가 길어지고 TTFT가 증가한다.
- 디코드도 GPU 경쟁으로 먼저 조금 느려졌다가 큐가 쌓이면 훨씬 느려진다.
- 이 현상은 underlying GPU의 contention과 대기열 증가가 응답 지표로 드러난 사례다.
-
오토스케일링으로 혼잡 해소
- 시스템이 증가한 부하를 감지하면 새 복제본을 띄운다.
- 새 복제본이 온라인이 되어 요청을 나누어 받으면 큐 길이와 혼잡이 기준선으로 내려간다.
- 많은 서비스에서 추가 자원을 확장해 큐와 혼잡을 해결하는 방식이 기본 해법이다.
-
깊은 프로파일링
- NSYS와 PyTorch Profiler는 전체 엔진을 한 번에 보는 핵심 도구다.
- 모든 프로세스와 GPU 작업을 한 화면에서 확인할 수 있다.
- 어떤 GPU만 전체적으로 느린 문제를 찾았고, 원인이 NUMA 인식 문제였던 사례가 있다.
8. 워크숍의 마무리와 실용 자료
8.1. 직접 읽고 실행할 자료
-
단순한 엔진 구현
- mini-SGLang과 Nano-vLLM은 추론 엔진 아키텍처를 단순화한 좋은 출발점이다.
- 사람이 코드를 읽기 좋고, 에이전트가 전체 컨텍스트를 한 번에 넣고 질문하기에도 적합하다.
- vLLM의 구조는 Alexa Gordic의 훌륭한 walkthrough 블로그로 보완할 수 있다.
-
에이전트와 함께 소스 읽기
- 슬라이드를 공유하고 노트북에서 코드를 직접 실행해 보라는 권고가 있었다.
- 코딩 에이전트에게 저장소를 가리키고 아키텍처 질문을 하면 코드 탐색을 빠르게 할 수 있다.
- Cognition의 DeepWiki는 SGLang과 vLLM을 포함한 여러 저장소를 크롤링해 아키텍처 다이어그램과 위키식 설명을 생성한다.
- DeepWiki의 에이전트에게 후속 질문을 던지면 자신의 코딩 에이전트 설정과 함께 읽기 도구로 쓸 수 있다.
8.2. 마지막 공지
-
Modal 배포 시작점
- Modal은 자체 추론을 배포·소유하려는 팀을 위한 새 제품을 제공한다.
- Modal Endpoints로 쉽게 배포를 시작하고, 합리적으로 최적화된 초기 기준선(baseline)을 얻은 뒤 자체 최적화를 이어갈 수 있다.
-
채용 안내와 박수
- 수백 팀의 추론 배포를 돕는 일에 관심이 있다면 Modal 채용 공고를 확인하라는 안내가 있었다.
- Charles Frye가 감사 인사를 전한 뒤 박수가 나왔고, 음악이 흐르며 59분 58초 세션이 끝났다.
주요 발언 모음
“높은 수준에서 토큰을 받아 토큰을 내놓는 일은 그렇게 어렵지 않다. 좋은 토크노믹스로 토큰을 생산할 만큼 극도로 높은 성능을 만드는 일이 어렵다.”
“학습은 비용 센터이고, 추론은 수익 센터다.”
“성능을 신경 쓰지 않으면 무상태지만, 성능을 신경 쓰는 순간 거의 모든 경우에 상태가 된다.”
“GPU에서 실제로 많은 일을 하는 것은 모델 러너지만, 스케줄러는 그 GPU의 게이트키퍼다.”
“큐잉을 문제로 취급한다. 계속 자라는 큐를 원하지 않고 가능한 빨리 비워지기를 원한다.”
“더 좋은 추측 모델을 학습하면 2배, 4배, 8배의 디코드 속도 향상을 얻을 수 있다.”
“성능 지표는 필요하다고 생각하는 것보다 더 많이 기록해야 한다. 어떤 교차 상관관계가 버그를 아주 쉽게 드러낼지 모르기 때문이다.”
핵심 데이터 & 수치
- 10~15분: 질문을 위해 남겨 둔 시간이며, 발표자는 청중이 손을 들고 즉시 끼어드는 상호작용 방식을 요청했다.
- 수십~수백~최대 수천 QPS: 추론 복제본의 일반적인 요청 처리 규모로, HTTP 자체보다 GPU 실행이 병목이 되기 쉽다.
- 수십~수백 토큰: Chatbot-plus의 전형적인 짧은 디코드 출력 길이다.
- 수백 밀리초: 사람이 대화형 응답에서 기다리기를 기대하는 대략적인 시간 한계다.
- 100,000 대 10,000 토큰: 충분히 큰 입력에서는 처리 시간이 입력 길이에 거의 선형으로 늘어나므로 10배 입력이 대략 10배 계산을 요구한다.
- 20B 파라미터: 이보다 큰 모델에서는 일반 토크나이저가 병목으로 드러나지 않는 경우가 많다는 경험적 기준이다.
- 1,000토큰/초: 디코드 처리량 기준으로 토큰당 평균 약 1ms이며, NVIDIA 하드웨어에서 큰 모델을 운영할 때 추측 디코딩의 목표 사례로 제시됐다.
- 10~20ms 이상: 처리량이 낮은 대형 모델에서 출력 토큰 하나의 디코드 지연이 커질 수 있는 범위다.
- 1TB 또는 100GB/토큰: 디코드가 토큰마다 읽을 수 있는 모델 파라미터 데이터의 규모 예시다.
- 페타바이트/초: 위와 같은 순차 메모리 접근이 요구할 수 있는 극단적인 메모리 대역폭 규모다.
- 2배·4배·8배: 좋은 speculator를 학습해 얻을 수 있는 기준선 대비 대략적인 속도 향상 예시다.
- 세 복제본: 아트 프로젝트에 부하를 주고 오토스케일링·큐·TTFT 변화를 관찰한 대시보드 사례의 복제본 수다.
결론 및 시사점
- 추론 엔진의 핵심은 모델 forward pass 하나가 아니라 서버 I/O, 토큰화, 스케줄러, 동적 배칭, 모델 러너, 디토큰화가 이어지는 실행 시스템이다.
- 프리필과 디코드를 같은 요청의 단일 덩어리로 취급하면 지연시간과 처리량의 상충을 놓치므로 두 하위 워크로드를 따로 측정해야 한다.
- 실제 엔진의 차별화는 공용 커널의 원시 성능보다 배치 구성, KV 캐시 용량·레이아웃, 스케줄러가 GPU를 공급하는 방식에서 나온다.
- 성능을 위해 무상태 API처럼 보이는 시스템도 KV 캐시와 세션 배치 때문에 상태성 운영이 필요하다.
- 계속 커지는 큐, KV 캐시 스래싱, CPU-GPU 동기화는 모두 GPU를 충분히 활용하지 못한다는 경고 신호다.
- 스케줄러는 연산량이 작아도 GPU의 게이트키퍼이므로 GPU가 빨라질수록 호스트 측 지연과 Rust 재작성 가능성이 중요해진다.
- CUDA Graph는 커널별 CPU 런치 오버헤드를 하나의 그래프 실행으로 줄여 호스트가 GPU를 막지 않게 하는 실용적인 수단이다.
- Speculative decoding은 순차 디코드를 작은 프리필로 바꾸고, 엔진의 미세 최적화보다 큰 폭의 처리량 향상을 제공할 수 있다.
- 모델 출시 때 토크나이저와 채팅 템플릿을 검증하고 토큰 ID를 로그해야 모델 품질 문제와 엔진 문제를 분리할 수 있다.
- 배포 전 평가, 프로덕션 trace, 충분한 메트릭, NSYS·PyTorch Profiler를 결합해야 장기 성능 회귀와 NUMA 같은 이기종 환경 문제를 찾을 수 있다.
- 추론을 배우려면 mini-SGLang·Nano-vLLM을 읽고 노트북에서 실행한 뒤, 코딩 에이전트나 DeepWiki로 실제 저장소의 데이터 흐름을 질문하는 순서가 효과적이다.
- 추론 인프라는 애플리케이션 요구사항에서 GPU 커널과 하드웨어까지 연결되며, 비용 센터인 학습을 수익 센터인 서비스로 바꾸는 운영 계층이다.
핵심 요약 (20줄)
- 추론 엔진은 토큰을 받아 다음 토큰을 내놓는 코드를 넘어 GPU를 계속 바쁘게 만드는 실행 시스템이다.
- 학습은 비용 센터인 반면 추론은 사용자가 비용을 지불하는 수익 센터다.
- Chatbot-plus는 사람과 툴 호출을 함께 상대하며 수백 밀리초 수준의 응답성을 요구한다.
- 백그라운드 에이전트는 몇 분에서 몇 시간의 여유를 갖고 높은 품질의 작업을 완성한다.
- 데이터 프로세서는 긴 비정형 입력을 짧은 구조화 객체로 바꾸며 집계 처리량을 중시한다.
- 프리필은 입력 전체를 처리하고 디코드는 한 번에 한두 토큰씩 출력한다.
- TTFT와 inter-token latency는 프리필·디코드 성능을 판단하는 핵심 SLO다.
- KV 캐시 재사용률은 사용자 입력과 에이전트 시스템 프롬프트의 구조에 따라 달라진다.
- 추론 서버는 HTTP/gRPC 경계를 맡고 추론 엔진은 토큰과 GPU 실행을 조율한다.
- 스케줄러는 연산량이 작아도 GPU에 일을 공급하는 게이트키퍼라 병목이 될 수 있다.
- 성능을 원하면 KV 캐시와 세션 때문에 추론 서비스는 사실상 상태성을 갖는다.
- 긴 입력은 토크나이저보다 모델 코어 루프와 반복 큐 대기 때문에 첫 토큰을 늦춘다.
- Python은 GIL을 피하려고 여러 프로세스를 사용하지만 GPU·C++ 상호운용성 때문에 계속 유용하다.
- Rust 재작성은 모델 워커보다 얇고 호스트 측인 스케줄러에서 큰 효과를 낼 가능성이 높다.
- 공용 커널이 원시 GPU 성능을 평준화하므로 엔진의 특수성은 배칭과 캐시 관리에서 나타난다.
- Paged·radix KV 캐시는 공통 접두사와 수만 토큰 시스템 프롬프트의 계산을 공유한다.
- CUDA Graph는 여러 커널 런치를 하나의 DAG 실행으로 묶어 CPU-GPU 동기화를 줄인다.
- Speculative decoding은 후보 토큰을 병렬 검증해 디코드 처리량을 2배·4배·8배까지 높일 수 있다.
- 배포 전 평가와 토큰 ID 로그는 모델 품질 버그와 엔진 정확성 버그를 분리한다.
- 큐·KV 스래싱·NUMA 문제를 찾으려면 대시보드, trace, NSYS, PyTorch Profiler와 과한 수준의 메트릭이 필요하다.
