AEGLOSLAB 엔비디아 기술 스택

제5부 추론 최적화와 서빙

5.8 TensorRT-LLM II — 인플라이트 배칭·페이지드 KV

5.8.1 이 장에서 배우는 것 / 선수 지식

5.7에서 KV 캐시가 LLM 추론 메모리·처리량의 핵심이고, 인플라이트 배칭·페이지드 KV가 그것을 푸는 레버라는 원리를 세웠다. 이 장은 그 둘을 운영 수준으로 판다 — 요청들이 제각각 끝나는 batch를 어떻게 매 스텝 다시 채워 GPU를 유휴 상태로 두지 않는지(인플라이트/연속 배칭), KV를 작은 블록으로 분할해 단편화를 없애 동시성을 끌어올리는 페이지드 KV, 그리고 KV가 모자랄 때의 스케줄링·preemption까지.

이것은 5.1의 "배치=마스터 노브"와 "decode는 메모리 바운드"가 실제 처리량으로 바뀌는 지점이다. 정적 배칭으로는 GPU가 약 절반 유휴 상태이고, 인플라이트 배칭+페이지드 KV로 그 빈자리를 메워 같은 GPU에서 처리량을 몇 배로 끌어올린다.

배우는 것:

  • 정적 배칭의 두 낭비 — 길이 패딩(compute·memory)과 종료 대기(GPU 유휴 버블) — 와 그것이 처리량을 어떻게 낮추는지.
  • 인플라이트(연속) 배칭 — 매 디코딩 스텝(iteration) 단위로 끝난 요청을 빼고 새 요청을 넣는 메커니즘. Triton 동적 배칭(5.13)과의 차이.
  • prefill/decode 혼합 스케줄링·청크 prefill — 긴 프롬프트가 decode를 막지 않게 하는 법.
  • 페이지드 KV — 블록 단위 할당·블록 매니저·free 풀, 단편화 제거, prefix 공유(KV 재사용).
  • KV 고갈 시 스케줄링 — admission(수용)·preemption(축출/재계산)·우선순위.
  • 빌드·런타임에서 켜고 튜닝하는 법, 정적 대비 처리량 벤치마크(실습).

선수 지식: 5.7(KV 캐시·페이지드 KV 도입·trtllm-build·KV 예산), 5.1(prefill/decode·배치·goodput·메모리 바운드), 3.6~3.7(어텐션), 2.13(Nsight로 활용률·버블 보기), 5.11/5.13(Triton 서빙·동적 배칭 — 구분). 환경은 5.7.

정직: 인플라이트 배칭·페이지드 KV의 설정 인자명·스케줄러 정책·기본값은 TRT-LLM 버전마다 다르다(max_num_tokens·kv_cache_free_gpu_mem_fraction·scheduler policy 등). 이 장은 메커니즘과 튜닝 사고를 중심에 두고 인자는 한 시점의 형태를 예시 — 정확한 이름·범위는 그 버전 문서로 확인. 페이지드 어텐션은 vLLM이 대중화한 공통 기법이다(엔비디아 전용 아님). 모든 수치는 환경 의존 개략값, 실측.

5.8.2 정적 배칭의 두 낭비

5.1의 배치는 "여러 요청을 한 번에"였다. 가장 단순한 구현 — 정적(static) 배칭 — 은 batch를 한 번 묶어 모두 끝날 때까지 함께 처리한다. 여기엔 LLM 특유의 두 낭비가 있다.

정적 배칭(4요청). 출력 길이가 제각각이다:

req A 8토큰 req B 2토큰(끝) req C 12토큰 req D 4토큰 가장 긴 C(12스텝)까지 batch 유지 — 점선 구간은 패딩/버블

파랑은 실제로 토큰을 만드는 활성 구간, 점선 회색은 비어 버린 슬롯이다. B는 2스텝에 끝났지만 정적 batch는 가장 긴 C(12스텝)가 끝날 때까지 유지된다 — 먼저 끝난 B·D·A가 비운 자리는 '패딩'으로 계산되거나 GPU가 유휴가 되어(버블) 활용률을 낮춘다.

낭비 ① 종료 대기(GPU 유휴 버블). 요청마다 EOS(종료) 시점이 다른데, 정적 batch는 가장 긴 요청이 끝날 때까지 batch를 유지한다. 먼저 끝난 요청의 슬롯은 빈자리(패딩)로 계산되거나 GPU가 유휴 상태가 되어 활용률이 떨어진다.

낭비 ② 길이 패딩. 프롬프트 길이도 제각각인데 한 batch로 묶으려면 최대 길이에 패딩한다 → 패딩 토큰에 쓸데없는 compute·KV 메모리. (prefill에서 특히.)

결과: 정적 배칭은 GPU를 약 절반 유휴 상태로 만든다. decode가 메모리 바운드라 배치로 채워야 처리량이 나오는데(5.1.4), 빈 슬롯이 그 채움을 깨뜨린다. 인플라이트 배칭이 이 빈자리를 새 요청으로 메운다.

5.8.3 인플라이트(연속) 배칭 — 메커니즘

핵심 아이디어: batch를 "요청 단위"가 아니라 "스텝(iteration) 단위"로 관리한다. 매 디코딩 스텝마다:

batch 구성원이 매 스텝 바뀜 · GPU가 항상 채워진 채 실행된다 매 스텝 (iteration) 시작 1) 끝난(EOS) 요청을 batch에서 즉시 제거 → KV 슬롯 반납 2) 대기 큐의 새 요청을 빈 슬롯에 즉시 투입 (prefill 후 decode 합류) 3) 현재 batch 구성원으로 한 스텝 forward

인플라이트 배칭(같은 4요청 + 대기 E·F·G):

슬롯1 A (8토큰) E 투입 슬롯2 B F 투입 슬롯3 C (12토큰) 슬롯4 D G 투입 빈 슬롯이 생기는 즉시 새 요청(E·F·G)으로 메움 → GPU 유휴 제거

파랑은 진행 중인 요청, 주황은 빈 슬롯에 새로 투입된 요청이다. A가 끝나자마자 E, B(2토큰)가 끝나자마자 F, D가 끝나자마자 G가 즉시 합류한다.

정적 vs 인플라이트:

정적 배칭인플라이트(연속) 배칭
단위요청 batch 전체스텝(iteration)
종료 처리가장 긴 요청까지 대기끝난 즉시 제거·교체
GPU 활용버블 많음항상 채움(높음)
처리량낮음높음(몇 배 가능, 개략)
지연큐 대기 길 수 있음빈 슬롯 즉시 수용 → 대기↓

Triton 동적 배칭(5.13)과 혼동 금지. Triton 동적 배칭은 요청 단위로 들어오는 요청을 잠깐 모아 한 batch로 묶는다(단발 추론·전체 모델 1회용에 적합). 인플라이트 배칭은 자기회귀 디코딩의 스텝 단위로 batch를 재구성한다(LLM 전용). LLM은 TRT-LLM의 인플라이트 배칭을 쓰고, Triton은 그 위에서 요청을 라우팅·스트리밍한다(5.11 TRT-LLM 백엔드).

5.8.4 prefill과 decode를 한 batch에 — 청크 prefill

새 요청이 합류하려면 먼저 prefill(프롬프트 처리, 컴퓨트 바운드)을 해야 한다. 그런데 prefill은 부하가 크다(긴 프롬프트는 더). 진행 중인 다른 요청들의 decode(메모리 바운드)와 한 스텝에 섞을 때 문제가 생긴다:

진행 중 긴 프롬프트 요청의 prefill 진행 중 요청들의 decode 지연 그 요청들의 TPOT (토큰 간 지연) 스파이크 사용자 체감 끊김

청크 prefill(chunked prefill). 긴 prefill을 여러 청크로 분할해 여러 스텝에 나눠 처리한다. 그러면 한 스텝이 prefill로 독점되지 않고, decode와 prefill 청크를 섞어 진행 중 요청의 TPOT 스파이크를 완화한다.

청크 없이 청크 prefill 스텝 k: 긴 prefill 전체 → 이 스텝 동안 decode들 정체 (TPOT↑) 스텝 k: prefill 조각1 + decode들 스텝 k+1: prefill 조각2 + decode들 ...

청크 prefill은 긴 prefill을 여러 스텝에 분산해 decode 흐름을 유지한다(TTFT는 약간↑, TPOT 안정).

트레이드오프: 청크 prefill은 새 요청의 TTFT를 약간 늘리는 대신(prefill이 여러 스텝에 분산) 진행 중 요청의 TPOT 안정성을 얻는다. 스케줄러 정책(처리량 우선 vs 지연 우선)으로 균형을 맞춘다(버전 의존).

5.8.5 페이지드 KV — 블록 관리로 단편화 제거

5.7에서 본 페이지드 KV를 운영 관점으로. 문제는 연속 KV 할당의 단편화다:

연속 KV(naive)는 요청마다 max_seq_len만큼 연속 블록을 예약한다:

req A 예약 8192 · 실제 800만 씀 → 90% 낭비 req B 예약 8192 · 실제 100토큰 빈 공간(회색)이 흩어져 새 요청을 못 받음 (단편화) → 동시성↓

파랑은 실제로 쓰는 KV, 회색은 예약했으나 안 쓰는 빈 공간이다.

페이지드 KV: KV를 고정 크기 블록(페이지) 으로 분할하고, 요청이 자라는 만큼 필요할 때 블록을 할당한다(OS 가상메모리와 동형).

페이지드 KV는 KV를 블록 풀(블록 = 예: 16토큰 분량)로 관리한다:

블록 풀 b0 b1 b2 b3 b4 b5 b6 b7 … req A (800토큰) → b0·b3·b5·b8… (50블록, 논리적으로 연속 매핑) req B (100토큰) → b1·b2·b6… (7블록) 빈틈 없이 채움 · 종료 시 블록 반납 → 재사용 단편화 제거 → 동시 요청 수↑ → 처리량↑

파랑은 req A, 주황은 req B가 점유한 블록, 회색은 free 풀에 남은 블록이다. 물리적으로 흩어져 있어도 논리적으로는 연속으로 매핑된다.

블록 매니저가 하는 일:

  • 할당: 요청이 토큰을 더 만들면 새 블록을 free 풀에서 가져옴. 풀이 비면 그 요청은 더 못 자람 → 스케줄러가 개입(5.8.6).
  • 반납: 요청 종료 시 블록을 free 풀로 → 즉시 다른 요청에 재사용(인플라이트 배칭과 짝).
  • 블록 크기 트레이드오프: 작으면 단편화↓·관리 오버헤드↑, 크면 반대. 보통 토큰 수십 단위(버전 의존).

prefix 공유(KV 재사용). 여러 요청이 같은 프롬프트 접두(prefix) 를 가지면(시스템 프롬프트·공통 문맥·few-shot 예시) 그 prefix의 KV 블록을 공유할 수 있다 — 한 번만 계산·저장하고 여러 요청이 가리킨다(copy-on-write). 효과:

  • prefill 절감: 공통 prefix를 매 요청 재계산하지 않음 → TTFT↓·compute↓.
  • 메모리 절감: 같은 KV를 공유 → 동시성↑.
  • 예: 챗봇의 긴 시스템 프롬프트, RAG의 공통 문서, 동일 few-shot. (기능명·가용성 버전 의존: prefix caching / KV reuse.)

5.8.6 KV 고갈과 스케줄링 — admission·preemption

페이지드 KV로도 블록 풀은 유한하다. 동시 요청이 많거나 시퀀스가 길어지면 KV가 고갈된다. 스케줄러의 결정:

매 스텝 스케줄러 admission (수용): 대기 요청을 batch에 넣을까? → 새 요청의 prefill KV를 감당 가능한가 진행 요청의 성장: decode로 토큰↑ → 블록 추가 필요 → 풀에 여유 있나 KV 고갈 시 preemption (축출) 우선순위· 공정성: 어떤 요청을 먼저/ 유지할지 (정책 의존) 일부 요청을 batch에서 빼고 그 KV를 회수 빠진 요청은 나중에 재개 (recompute prefill 또는 KV를 CPU로 swap)

preemption의 두 방식(버전·구현 의존):

  • recompute(재계산): 축출된 요청의 KV를 버리고, 재개 시 prefill을 다시 계산. 메모리 회수는 간결하나 compute 낭비.
  • swap(스왑): 축출된 요청의 KV를 CPU 메모리로 내림, 재개 시 다시 적재함. compute는 아끼나 PCIe 전송 비용(2.5).

함정: KV 여유가 적은데 동시 요청을 무리하게 받으면 preemption thrashing(축출↔재개 반복)으로 처리량이 오히려 무너진다. admission을 보수적으로(KV 여유를 보고 수용) 두는 것이 안정적 — 처리량과 지연 안정성의 균형을 스케줄러 정책으로 맞춘다.

5.8.7 워크스루 — 켜고 튜닝하고 측정

빌드·런타임에서 인플라이트 배칭·페이지드 KV를 켜고 정적과 비교한다(인자명 버전 의존, 문서 확인).

# 1) 빌드: 페이지드 KV·인플라이트 배칭 지원으로(대개 기본 권장)
trtllm-build --checkpoint_dir ./ckpt --output_dir ./engine \
    --gemm_plugin auto \
    --paged_kv_cache enable \
    --remove_input_padding enable \
    --max_batch_size 64 \
    --max_num_tokens 8192 \
    --max_seq_len 4096
# remove_input_padding=패딩 제거(길이 낭비↓) · ★max_num_tokens=한 스텝 처리 토큰 총량 상한(인플라이트 배칭의 핵심)

런타임/서빙 핵심 손잡이(개념):

손잡이의미튜닝
max_num_tokens한 iteration에 처리하는 토큰 총합 상한(prefill+decode)너무 작으면 처리량↓, 크면 지연 스파이크·메모리↑
KV free mem fractionKV 캐시에 줄 GPU 메모리 비율크게=동시성↑(다른 버퍼와 균형)
scheduler policy처리량 우선 vs 지연 보장(max_utilization vs guaranteed_no_evict 류)워크로드·SLA에 맞춤
chunked prefill긴 prefill 청크 분할긴 프롬프트 많으면 켜서 TPOT 안정
enable_kv_reuseprefix KV 공유공통 prefix(시스템 프롬프트·RAG) 많으면
# 2) 처리량 비교: 정적 vs 인플라이트(벤치 스크립트는 버전별)
#    동일 부하(동시성·시퀀스 분포)로 tokens/s·p99 TTFT/TPOT·GPU util 측정
#    인플라이트+페이지드가 정적 대비 tokens/s가 크게(개략 수배) 높고 util↑가 정상
python benchmark.py --engine ./engine --mode inflight  --concurrency 64
python benchmark.py --engine ./engine --mode static    --concurrency 64

3) Nsight Systems(2.13)로 타임라인 확인:

모드Nsight 타임라인에서 보이는 것
정적decode 사이 빈 구간(버블), GPU util 낮음
인플라이트GPU가 빽빽이 채워짐, util 높음

prefill 스파이크가 decode를 막으면 chunked prefill을 검토한다.

실무: TRT-LLM 인플라이트 배칭은 대개 Triton TRT-LLM 백엔드(5.11)로 서빙한다 — 요청 큐·스트리밍·메트릭을 Triton이, 인플라이트 디코딩을 TRT-LLM Executor가 맡는 조합. 직접 Executor를 호출할 수도 있다(버전별 API).

5.8.8 중간 점검 (체크포인트)

  • [ ] 정적 배칭의 두 낭비(종료 대기 버블·길이 패딩)와 그것이 처리량을 낮추는 이유를 설명한다.
  • [ ] 인플라이트 배칭이 스텝 단위로 끝난 요청을 빼고 새 요청을 넣어 GPU를 채우는 메커니즘을, Triton 동적 배칭과 구분해 말한다.
  • [ ] 청크 prefill이 진행 중 요청의 TPOT 스파이크를 왜·어떻게 완화하는지 안다.
  • [ ] 페이지드 KV의 블록 관리(할당·반납·블록 크기)가 단편화를 없애 동시성을 높이는 원리와, prefix 공유의 이득을 설명한다.
  • [ ] KV 고갈 시 admission·preemption(recompute/swap) 결정과 thrashing 위험을 안다.
  • [ ] 빌드·런타임에서 켜고(paged_kv_cache·max_num_tokens 등) 정적 대비 처리량·활용률을 측정한다.

증상→의심: GPU 활용률 낮고 처리량 안 나옴 → 정적 배칭·인플라이트 미사용 → 켜기. tokens/s가 어느 지점부터 안 오름 → max_num_tokens·KV 메모리 한계 → 늘리거나 병렬(5.9). 진행 요청 TPOT가 가끔 튐 → 긴 prefill이 decode 방해 → chunked prefill. 처리량이 출렁이며 떨어짐 → preemption thrashing(KV 고갈) → admission 보수적·KV 메모리↑·동시성↓. 공통 시스템 프롬프트인데 TTFT 높음 → prefix KV 재사용 미사용 → enable_kv_reuse.

5.8.9 트레이드오프·대안

처리량 우선 vs 지연 보장. 스케줄러 정책의 핵심 갈래.

정책누구에게비고
처리량 최대(공격적 수용)배치 처리·비용 최소·느슨한 SLA동시성·tokens/s↑, p99 꼬리·preemption 위험↑
지연 보장(보수적 수용·no-evict)대화형·엄격한 p99안정적 TPOT, 처리량은 다소↓
청크 prefill on긴 프롬프트 섞임TPOT 안정(진행 요청), 새 TTFT 약간↑
prefix 재사용 on공통 prefix 많음TTFT·메모리↓, 캐시 관리 오버헤드

견해: 대화형 서비스는 지연 보장 쪽 + 청크 prefill, 오프라인 대량 생성은 처리량 최대로 가는 것이 자연스럽다. 둘 다 필요하면 운영점을 분리(요청 클래스별 정책·풀). 핵심은 admission을 KV 여유에 맞춰 보수적으로 두어 thrashing을 피하는 것 — 무리한 동시성은 처리량을 오히려 낮춘다. 모든 정책은 부하 생성기로 p99·goodput 곡선을 그려 운영점을 실측으로 정한다(5.1).

비엔비디아 정직: 페이지드 어텐션·연속 배칭은 vLLM이 대중화한 공통 기법이고 SGLang 등도 제공한다(SGLang은 RadixAttention 등 prefix 공유를 강조). TRT-LLM의 차별점은 엔비디아 커널·FP8/FP4·트랜스포머 엔진·NVLink 병렬·Triton 통합이다. 처리량·지연 우열은 모델·하드웨어·시점마다 다르니 당신 워크로드로 vLLM/SGLang과 실측 비교(5.15).

5.8.10 흔한 함정

  • 정적 배칭을 인플라이트로 착각. 인플라이트 배칭을 안 켜면(또는 정적 모드) GPU가 유휴 상태이고 처리량이 안 난다. paged KV·인플라이트 활성화 확인.
  • Triton 동적 배칭과 혼동. 동적 배칭(요청 단위, 5.13)은 단발 추론용. LLM 자기회귀는 인플라이트 배칭(스텝 단위) — 둘은 다른 계층.
  • max_num_tokens 과소. 한 스텝 토큰 상한이 작으면 batch를 못 채워 처리량↓. 메모리·지연과 균형 맞춰 충분히.
  • KV 무리 수용 → preemption thrashing. 동시 요청을 KV 여유 이상으로 받으면 축출↔재개 반복으로 처리량 붕괴. admission 보수적.
  • 긴 prefill로 decode 정체. 청크 prefill 없이 긴 프롬프트가 들어오면 진행 요청 TPOT가 튐. chunked prefill.
  • prefix 재사용 미활용. 공통 시스템 프롬프트·RAG 문맥을 매 요청 재계산하면 TTFT·메모리 낭비. KV reuse(가용 시).
  • max_seq_len·max_batch를 부하 분포 무시하고 설정. KV 예산이 어긋나 OOM이나 저활용. 실제 분포로(5.7).
  • 인자명을 버전 불문 복붙. 스케줄러 정책·인자가 릴리스마다 변함 — 그 버전 문서.

5.8.11 연습문제

연습 1 (정적의 낭비). 출력 길이가 [3,3,3,300] 토큰인 4요청을 정적 배칭으로 실행한다. (a) GPU가 낭비되는 지점을 설명하고, (b) 인플라이트 배칭이 이를 어떻게 바꾸나, (c) 처리량 개선의 대략적 크기는?

정답

(a) 정적은 가장 긴 요청(300토큰)이 끝날 때까지 batch 유지 → 짧은 3개는 3스텝에 끝났는데 297스텝 동안 그 슬롯이 빈자리(패딩/유휴). 4개 중 3개 슬롯이 사실상 유휴여서 GPU 활용률·처리량 급락. (b) 인플라이트는 3토큰 요청이 끝나는 즉시 슬롯을 반납하고 대기 큐의 새 요청을 투입 → 빈 슬롯이 계속 새 작업으로 채워짐. (c) 이 극단 예에서 정적은 사실상 1요청(300토큰)분 처리량인데, 인플라이트는 빈 3슬롯을 계속 실행해 이론상 수배 처리량(부하·KV 여유에 따라). 실제 크기는 시퀀스 분포·동시성·KV로 결정 → 실측.

연습 2 (인플라이트 vs 동적 배칭). 동료가 "Triton 동적 배칭을 켰으니 LLM 처리량이 최적"이라 한다. 무엇이 잘못된 이해이고, 올바른 구성은?

정답

잘못: Triton 동적 배칭(요청 단위) 은 단발 추론(전체 모델 1회 forward, 예: 분류)을 잠깐 모아 묶는 것으로, 자기회귀 디코딩의 스텝 단위 동역학을 다루지 않는다. LLM은 토큰을 수백 번 생성하며 요청이 제각각 끝나므로, 인플라이트(연속) 배칭(스텝 단위) 이 필요하다 — 이것은 TRT-LLM Executor가 한다. 올바른 구성: TRT-LLM 엔진(paged KV·인플라이트 배칭) + Triton TRT-LLM 백엔드(5.11) — Triton은 요청 큐·스트리밍·메트릭을, 인플라이트 디코딩은 TRT-LLM이. 동적 배칭 토글이 아니라 인플라이트 배칭이 핵심.

연습 3 (페이지드 KV). 연속 KV 할당에서 단편화가 왜 생기고 동시성을 어떻게 낮추는지, 페이지드 KV가 이를 어떻게 푸는지 블록 관점에서 설명하라. prefix 공유가 추가로 주는 이득은?

정답

연속 할당: 요청마다 최대 길이만큼 연속 공간을 예약하지만 실제 길이는 짧고 제각각이라 예약했으나 안 쓰는 빈틈이 흩어진다(단편화) → 합치면 새 요청 하나가 들어갈 메모리인데 연속 공간이 없어 못 받음 → 동시성↓. 페이지드 KV: KV를 고정 블록으로 분할해 요청이 자라는 만큼 free 풀에서 블록을 할당, 종료 시 반납 → 빈틈 없이 채우고 재사용(논리적으로만 연속, 물리적으로 흩어져도 됨) → 같은 HBM으로 동시 요청↑. prefix 공유: 공통 프롬프트 접두의 KV 블록을 여러 요청이 공유(copy-on-write) → 공통 prefill 재계산 제거(TTFT↓)·메모리 절감(동시성↑).

연습 4 (preemption). 처리량을 높이려 admission을 공격적으로 키웠더니 처리량이 오히려 출렁이며 떨어졌다. 무슨 일이며, recompute와 swap 중 어떤 preemption이 쓰였을지와 각 비용, 해결책은?

정답

무슨 일: KV 여유보다 많은 요청을 받아 KV 고갈 → preemption(축출) 이 빈발, 축출된 요청을 재개하느라 자원을 쓰고 다시 축출되는 thrashing → 유효 처리량 붕괴·출렁임. preemption 비용: recompute(KV 버리고 재개 시 prefill 재계산) = compute 낭비, swap(KV를 CPU로 내보냄/적재함) = PCIe 전송 비용(2.5). 어느 쪽이든 thrashing이면 손해. 해결: admission을 보수적으로(KV 여유를 보고 수용), max_batch/동시성↓, KV 메모리 비율↑, 긴 시퀀스 분리. 처리량은 "무리한 동시성"이 아니라 thrashing 없는 안정 운영점에서 최대 — p99·goodput 곡선으로 그 점을 찾는다.

연습 5 (정책 선택). (a) 엄격한 p99 TPOT의 대화형 코드 어시스턴트, (b) 야간 대량 문서 요약(지연 느슨, 비용 최소), (c) 긴 시스템 프롬프트를 모든 요청이 공유하는 챗봇. 각각에 스케줄러·기능 설정을 제안하라.

정답

(a) 지연 보장 정책(보수적 admission/no-evict) + 청크 prefill — TPOT 안정이 최우선, preemption·prefill 간섭 회피. 동시성은 SLA 한도까지. (b) 처리량 최대 정책(공격적 수용) — 느슨한 SLA라 GPU를 빽빽이 채워 tokens/s·$/토큰 최적, preemption 약간 감수. max_num_tokens·KV 메모리 크게. (c) prefix KV 재사용(enable_kv_reuse) on — 공통 시스템 프롬프트의 KV를 공유해 매 요청 prefill·메모리 절감(TTFT↓·동시성↑) + (대화형이면) 지연 보장·청크 prefill 병행. 모든 경우 부하 생성기로 p99·goodput·util을 측정해 운영점 확정.

5.8.12 요약 · 다음 장

  • 정적 배칭은 종료 대기 버블과 길이 패딩으로 GPU를 유휴 상태로 만든다. 인플라이트(연속) 배칭은 batch를 스텝 단위로 관리해 끝난 요청을 즉시 빼고 새 요청을 넣어 GPU를 채운다 → 처리량 몇 배(개략). Triton 동적 배칭(요청 단위)과는 다른 계층.
  • 청크 prefill은 긴 prefill을 분할해 진행 중 요청의 TPOT 스파이크를 완화한다(새 TTFT 약간↑ 대가).
  • 페이지드 KV는 KV를 블록으로 관리해 단편화를 없애 동시성↑, prefix 공유로 공통 prefill·메모리를 아낀다.
  • KV 고갈 시 admission·preemption(recompute/swap) 으로 스케줄 — 무리한 수용은 thrashing으로 처리량을 낮추니 보수적 admission이 안정적. 정책(처리량 vs 지연)을 워크로드에 맞춘다.
  • 빌드·런타임에서 paged_kv_cache·max_num_tokens·스케줄러 정책으로 켜고 튜닝하며, 대개 Triton TRT-LLM 백엔드로 서빙. 정직: 인자·정책은 버전 의존, 페이지드/연속 배칭은 공통 기법, 모든 수치 실측.

다음 장: 5.9 TensorRT-LLM III — 양자화·병렬(TP·PP). 한 GPU에 안 들어가는 큰 모델을 텐서 병렬(TP)·파이프라인 병렬(PP) 로 여러 GPU에 나누는 법(4.13~4.14의 NCCL·매핑과 연결)과, LLM 특화 양자화(FP8·가중치 INT4 AWQ/GPTQ 등) 가 추론 메모리·처리량을 어떻게 더 미는지를 본다.