AEGLOSLAB 엔비디아 기술 스택

제5부 추론 최적화와 서빙

5.9 TensorRT-LLM III — 양자화·병렬(TP·PP)

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

5.7~5.8에서 TRT-LLM의 KV 캐시·인플라이트 배칭·페이지드 KV로 한 GPU 안에서 LLM 추론 처리량을 확보했다. 그런데 모델이 한 GPU에 안 들어가면(가중치 + KV가 HBM 초과), 또는 지연을 더 줄이려면 어떻게 하나? 답은 둘이다 — ① 모델을 여러 GPU로 나누는 병렬화(텐서 병렬 TP·파이프라인 병렬 PP), ② 모델을 더 작은 정밀도로 압축하는 LLM 특화 양자화(weight-only INT4·FP8·SmoothQuant·KV 양자화). 이 장은 그 둘을, 그리고 언제 무엇을 쓰는지를 판다.

핵심 통찰 둘을 미리 확정한다. (1) 추론의 병렬화는 학습과 목적이 다르다 — 학습은 거대 배치 처리량이 목적이지만, 추론 TP는 지연 단축(decode 분산)이, PP는 노드 간 확장이 주 동기다. (2) LLM 양자화는 regime이 정한다 — 메모리 바운드 decode(작은 배치)는 weight-only INT4가, 컴퓨트 바운드 prefill·큰 배치는 FP8 W8A8이 자연스럽다.

배우는 것:

  • 왜 병렬화하나 — 메모리(모델이 한 GPU 초과)와 지연(작업 분산), 그리고 추론이 학습과 다른 점.
  • 텐서 병렬(TP) — 레이어 가중치를 GPU로 분할해 매 레이어 all-reduce, NVLink 도메인 안에 두어야 하는 이유(4.13~4.14).
  • 파이프라인 병렬(PP) — 레이어를 스테이지로 나눠 경계 P2P, 단일 요청의 파이프라인 버블과 그 함의.
  • TP×PP 조합과 인터커넥트 매핑(4.14 원리의 추론판).
  • LLM 양자화 — weight-only INT4(AWQ·GPTQ)·FP8(W8A8)·SmoothQuant·KV 양자화의 원리와 regime별 선택.
  • multi-LoRA 서빙 — 커스터마이즈된 변형마다 모델 전체를 복제하지 않고, 베이스 하나 + 경량 어댑터로 여러 태스크·테넌트를 서빙하는 법(5.9.13).
  • 빌드·실행에서 TP/PP·양자화를 켜는 흐름(실습).

선수 지식: 4.13~4.14(NCCL 집합연산·병렬화 매핑 — 이 장의 통신 토대), 5.4~5.5(양자화 PTQ/QAT·INT8·FP8 — 이 장의 정밀도 토대), 5.7(KV·가중치 메모리), 5.1(prefill/decode·메모리 바운드), 4.6~4.9(NVLink·도메인). 환경은 5.7.

정직: TP/PP 빌드 인자(tp_size·pp_size), 양자화 방법(AWQ·GPTQ·FP8·SmoothQuant)의 지원·인터페이스는 TRT-LLM 버전·모델마다 다르다. AWQ·GPTQ·SmoothQuant는 외부에서 제안된 방법을 TRT-LLM이 통합한 것으로 명칭·가용성이 변한다. 이 장은 원리·선택 기준을 중심에 두고 명령은 한 시점 형태를 예시 — 정확한 인자·지원은 그 버전 문서로 확인. 모든 수치는 환경 의존 개략값, 실측.

5.9.2 왜 병렬화 — 메모리와 지연

한 GPU로 부족한 두 경우:

한 GPU로 부족한 두 경우 ① 메모리: 가중치 + KV가 한 GPU HBM 초과 예: 70B 가중치 ≈ 140GB(FP16) → 80GB GPU 한 장에 안 들어감 여러 GPU에 가중치·KV를 '나눠 담아야' 함(TP 또는 PP) ② 지연: 한 GPU로 들어가도 더 빠르게 decode는 메모리 바운드 → 여러 GPU가 가중치를 나눠 읽으면 스텝이 빨라짐(TP) TPOT↓ (작은 배치 대화형에서 중요)

추론 병렬화 ≠ 학습 병렬화. 학습(4.14)은 거대 배치를 처리하는 데이터·텐서·파이프라인 병렬이 목적이었다. 추론은:

병렬학습에서추론에서
TP(텐서)큰 레이어 분산지연 단축 + 메모리 분산(decode를 여러 GPU가 나눠 읽음)
PP(파이프라인)노드 간 레이어 분산메모리 분산·노드 확장(단, 단일 요청 버블로 지연엔 불리)
DP(데이터)거대 배치추론은 복제(replica) 로 — 같은 모델 여러 벌로 처리량 수평 확장
EP(전문가)MoEMoE 추론도 EP(4.14)

추론에서 "데이터 병렬"은 보통 모델 복제본을 여러 개 기동해 요청을 분산(수평 확장)하는 것이고, 한 모델을 분할하는 것은 TP·PP다. 이 장은 후자(모델 분할).

5.9.3 텐서 병렬(TP) — 매 레이어 분산

텐서 병렬은 각 레이어의 가중치 행렬을 GPU들로 분할한다. 행렬곱을 분할해 각 GPU가 일부를 계산하고, 결과를 all-reduce(또는 all-gather)로 합친다(4.13).

입력 X (TP=2, 한 linear 레이어 Y = X·W) GPU0: W 왼쪽 절반 W0 Y0 = X·W0 GPU1: W 오른쪽 절반 W1 Y1 = X·W1 all-reduce/all-gather로 Y 합침 (매 레이어, 어텐션·MLP마다) 가중치가 GPU 수만큼 나뉨(메모리↓) 연산도 나뉨(지연↓) 단, '매 레이어 통신'이라 통신이 잦다 → NVLink 도메인 안이어야(4.14)

TP의 성질:

  • 메모리·지연 둘 다 이득: 가중치를 N등분(GPU당 메모리 1/N), decode의 가중치 읽기도 N등분(메모리 바운드 완화 → TPOT↓). 그래서 대화형 저지연에 TP가 핵심.
  • 통신이 잦다: 매 레이어(어텐션·MLP)마다 all-reduce. 이 통신이 NVLink 도메인 대역(4.6~4.7)에 묶이므로, TP는 NVLink로 묶인 GPU들(노드 내) 안에 둬야 한다. TP를 노드 경계(느린 네트워크) 넘겨 잡으면 통신이 병목이 되어 같은 GPU 수로도 훨씬 느려진다(4.14의 매핑 원리).
  • 확장 한계: TP를 무한히 키울 수 없다 — 통신 비중이 커지고 NVLink 도메인 크기(노드 내 GPU 수, 예 8)가 상한. 그 너머는 PP·복제로.

5.9.4 파이프라인 병렬(PP) — 레이어를 스테이지로

파이프라인 병렬은 레이어들을 GPU 스테이지로 나눈다(예: 레이어 1~20=GPU0, 21~40=GPU1). 활성화가 스테이지 경계를 P2P(점대점) 로 흐른다.

활성화 P2P PP=2 예 (40레이어) GPU0: 레이어 1~20 GPU1: 레이어 21~40 출력 통신은 '스테이지 경계'에서만(드물다) → 노드 간(느린 네트워크)도 견딤 단, 단일 요청은 한 번에 한 스테이지만 활성 → 나머지 스테이지 유휴 = '버블'

PP의 성질:

  • 통신이 드물다: 스테이지 경계에서만 P2P → 노드 간(InfiniBand)에 매핑 가능(4.14). TP가 NVLink 도메인을 넘지 못하는 한계를 PP가 보완.
  • 메모리 분산: 레이어를 나눠 GPU당 가중치·KV가 줄어듦.
  • 단일 요청 버블(지연 불리): 요청 하나가 GPU0→GPU1 순차로 흐르면 GPU1이 계산하는 동안 GPU0은 유휴 상태다. 단일 요청 지연엔 PP가 불리 — TP는 동시에 분산하지만 PP는 순차. 버블은 여러 요청(마이크로배치)을 파이프에 채워 완화(인플라이트 배칭과 결합, 5.8).

TP vs PP(추론):

축TPPP
통신 빈도매 레이어(잦음)스테이지 경계(드묾)
인터커넥트NVLink 도메인 안(4.14)노드 간 가능(IB)
단일 요청 지연단축(분산 계산)버블로 불리(순차)
처리량좋음버블 채우면 좋음
주 용도저지연·노드 내노드 확장·초대형 모델

견해(추론): 저지연·노드 내가 우선이면 TP를, 모델이 노드 하나로도 안 들어갈 만큼 크면 TP(노드 내)×PP(노드 간) 로 간다. 4.14의 매핑 원리 — "잦은 통신(TP)은 NVLink 도메인, 드문 통신(PP)은 노드 간" — 이 추론에도 그대로 적용된다.

5.9.5 TP×PP 조합과 매핑

큰 모델은 보통 TP×PP 조합이다. 매핑 원리는 4.14와 동일.

노드0 (NVLink 8장) 노드1 (NVLink 8장) 스테이지 경계 P2P · 노드 간 IB · 드묾 예: 16-GPU (노드 2개 × 노드당 8-GPU NVLink 도메인) TP=8 × PP=2 TP=8: 레이어 1~N 가중치를 8장에 분산 매 레이어 NVLink all-reduce TP=8: 레이어 N+1~2N TP는 NVLink 도메인 안(8), PP는 노드 경계(2)에 정렬 → 통신을 인터커넥트 계층에 맞춤

매핑을 어기면(예: TP를 노드 경계 넘김) 매 레이어 all-reduce가 느린 네트워크를 타 같은 GPU 수로도 몇 배 느려진다 — 4.14의 핵심 교훈. 총 GPU = TP × PP(× 복제본 수)이고, 각 차원을 그에 맞는 인터커넥트에 정렬하는 것이 성능의 핵심 요인.

추가: KV 캐시도 TP에 따라 분산된다(헤드를 GPU로 나눔) → GPU당 KV 메모리도 1/TP. PP는 레이어를 나누므로 스테이지별로 그 레이어의 KV를 보유. 병렬화는 가중치뿐 아니라 KV 예산(5.7)도 분산한다.

5.9.6 LLM 양자화 — regime이 정한다

5.4~5.5에서 INT8 PTQ·QAT·FP8을 일반적으로 배웠다. LLM 추론은 prefill/decode regime(5.1.6) 때문에 양자화 선택이 갈린다. 핵심 구분:

양자화 표기: W(가중치)A(활성화) — 예: W4A16 = 가중치 4비트·활성화 16비트.

regime병목양자화 선택효과
decode(메모리 바운드, 작은 배치)가중치를 HBM에서 읽는 것 → '가중치'만 줄이면 빠름weight-only INT4 (W4A16): 활성화는 FP16 유지, 가중치만 4비트가중치 읽기 1/4 → decode 속도·메모리 큰 이득
prefill·큰 배치(컴퓨트 바운드)연산 → 활성화도 줄여 'INT8/FP8 텐서코어'로 연산 가속FP8 W8A8 (또는 INT8 W8A8): 가중치·활성화 모두 8비트컴퓨트 처리량↑ (트랜스포머는 FP8 선호, 5.5)

① weight-only INT4 — AWQ·GPTQ. 가중치만 INT4로(활성화 FP16). decode가 메모리 바운드(가중치 읽기가 병목)라, 가중치를 1/4로 줄이면 읽을 바이트가 급감해 decode가 빨라지고 메모리도 크게 절감. 작은 배치·대화형에 특히 유효.

  • GPTQ: 2차 정보(헤시안 근사)를 이용해 레이어별로 가중치를 INT4로 양자화하며 오차를 보정(후처리, 캘리브레이션 데이터 사용).
  • AWQ(Activation-aware Weight Quantization): 활성화 크기를 보고 중요한(큰 활성화와 곱해지는) 가중치 채널을 보호하며 INT4 양자화 → 정확도 유지.
  • 공통: 후처리 weight-only라 빠르게 적용, 정확도는 보통 잘 유지(검증 필요). 활성화는 FP16이라 큰 배치 컴퓨트 바운드에선 이득이 작다(활성화 연산이 그대로).

② FP8 W8A8. 가중치·활성화 모두 FP8(5.5). 트랜스포머의 넓은 범위를 부동소수로 잘 담아 컴퓨트 바운드(prefill·큰 배치)에서 텐서코어 처리량을 끌어올린다. Hopper+ 세대(4.2). 트랜스포머에 INT8보다 자주 유리.

③ SmoothQuant — INT8 활성화를 가능하게. 트랜스포머 활성화는 이상치(outlier) 가 심해 INT8 균일 양자화가 어렵다(5.5에서 FP8이 유리한 이유). SmoothQuant는 활성화의 이상치 스케일을 가중치로 "이전(migrate)" 해 활성화를 평탄하게 만들어 INT8 W8A8을 실용화한다. (FP8이 없는/부적합한 환경에서 INT8 W8A8을 쓰고 싶을 때.)

④ KV 양자화. KV 캐시를 FP8/INT8로(5.7.5). 가중치·활성화 양자화와 독립적으로 조합 가능 — 동시성·decode 메모리 추가 이득.

여러 커스터마이즈 변형(부서별·태스크별 LoRA, 6.4)을 서빙해야 한다면, 모델 전체를 복제하는 대신 베이스 하나 + 경량 어댑터로 묶는 multi-LoRA 서빙을 본다(5.9.13 — 번호는 이 장 끝에 붙지만 내용은 이 절 바로 다음 자리).

regime별 선택 요약:

워크로드추천 출발이유
대화형·작은 배치·decode 고부하weight-only INT4(AWQ) + KV 양자화가중치 읽기 병목 직격, 메모리↓
큰 배치·prefill 고부하·처리량FP8 W8A8(Hopper+)컴퓨트 처리량↑, 트랜스포머 적합
FP8 불가 환경·INT8 W8A8 원함SmoothQuant INT8이상치 이전으로 INT8 활성화 실용화
정확도 최우선FP16 + KV 양자화만보수적

견해: 대화형 LLM은 weight-only INT4가 가성비 최강일 때가 많다(decode 메모리 바운드를 정확히 친다). 큰 배치 처리량 서비스·Hopper+면 FP8. 둘을 섞기도(예: W4A16 + FP8 KV). 항상 태스크 지표(퍼플렉시티·다운스트림)로 검증(5.5). "양자화=무비용"은 LLM에서도 아니다.

5.9.7 워크스루 — TP/PP·양자화 빌드·실행

개략 흐름(인자 버전 의존, 문서 확인):

# 1) 양자화하며 체크포인트 변환 (예: weight-only INT4 또는 FP8)
#    방법·인자는 모델·버전마다 다름 — 공식 예제/quantize 스크립트 참조
python quantize.py --model_dir ./hf_model --output_dir ./ckpt_int4 \
    --qformat int4_awq            # 예: AWQ W4 (또는 fp8, int8_sq(SmoothQuant) 등)
    # --calib_dataset ...         # AWQ/GPTQ/SmoothQuant는 캘리브레이션 데이터 사용

# 2) TP×PP로 엔진 빌드 (총 GPU = tp_size × pp_size)
trtllm-build --checkpoint_dir ./ckpt_int4 --output_dir ./engine \
    --gemm_plugin auto \
    --tp_size 8 \
    --pp_size 2 \
    --max_batch_size 64 --max_seq_len 4096 \
    --paged_kv_cache enable
    # tp_size=텐서 병렬(NVLink 도메인 안) · pp_size=파이프라인 병렬(노드 간) · KV 양자화 옵션은 별도(버전 의존)

# 3) 다중 GPU 실행 (MPI/NCCL로 16 rank). 런처는 버전별.
mpirun -n 16 python run.py --engine_dir ./engine --max_output_len 256 \
       --input_text "..."

검증·측정:

   · 정확도: 양자화 엔진의 퍼플렉시티·다운스트림 점수를 FP16 대비(5.5 검증 체계)
   · 성능: TP를 1→8 늘리며 TPOT(지연)·tokens/s 측정 → NVLink 도메인 안에서 확장하는지
   · 매핑 확인: TP가 NVLink로(노드 내), PP가 IB로(노드 간) 가는지 — 어긋나면 느림(4.14)
   · 양자화 regime: 작은 배치에서 W4A16, 큰 배치에서 FP8의 tokens/s를 비교

엔진은 TP/PP 구성·GPU·버전 종속이다(5.2·5.7). tp=8로 빌드한 엔진은 8-GPU 구성에서만 로드된다 — 구성을 바꾸면 재빌드. 보통 Triton TRT-LLM 백엔드(5.11)로 다중 GPU 서빙.

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

  • [ ] 병렬화의 두 동기(메모리·지연)와, 추론 병렬화가 학습과 다른 점(TP=지연, PP=노드 확장, DP=복제)을 설명한다.
  • [ ] TP가 매 레이어 all-reduce로 통신이 잦아 NVLink 도메인 안이어야 하는 이유와, 메모리·지연을 둘 다 줄이는 원리를 안다.
  • [ ] PP의 스테이지 P2P·단일 요청 버블·노드 간 매핑 적합성을 설명한다.
  • [ ] TP×PP 매핑(TP=NVLink, PP=IB)과 어겼을 때의 손해를 안다.
  • [ ] regime별 양자화 선택 — decode/작은 배치=weight-only INT4(AWQ/GPTQ), prefill/큰 배치=FP8 W8A8, INT8 활성화=SmoothQuant — 을 이유와 함께 제시한다.
  • [ ] TP/PP·양자화를 빌드·실행하고 정확도·성능을 검증한다.
  • [ ] multi-LoRA 서빙이 왜 모델 복제보다 메모리 효율적인지, 어댑터를 build-time에 무엇으로 제약하는지 안다(5.9.13).

증상→의심: TP 늘렸는데 지연이 안 줄거나 느려짐 → TP가 NVLink 도메인 초과(노드 경계)·통신 병목 → TP를 노드 내로, 초과분은 PP. PP인데 단일 요청 지연이 큼 → 파이프라인 버블(정상) → 마이크로배치·인플라이트 배칭으로 채움, 저지연이면 TP 우선. weight-only INT4인데 큰 배치에서 이득 작음 → 큰 배치는 컴퓨트 바운드(활성화 FP16) → FP8 W8A8 검토. INT8 활성화 정확도 붕괴 → 활성화 이상치 → SmoothQuant 또는 FP8. 양자화 엔진 로드 실패 → TP/PP·GPU·버전 불일치 → 대상 구성 재빌드.

5.9.9 트레이드오프·대안

병렬화 차원 선택.

차원누구에게비고
TP(노드 내)저지연·모델이 노드 하나엔 들어감매 레이어 통신, NVLink 필수, 지연·메모리↓
TP×PP모델이 노드 하나도 초과TP=NVLink·PP=IB 매핑, 초대형 모델
복제(replica)처리량 수평 확장모델이 한 GPU(또는 작은 TP)에 들어갈 때 여러 벌
양자화로 단일 GPU모델을 압축해 한 GPU에INT4/FP8로 메모리↓ → 병렬 없이 → 통신 0(가장 단순)

견해: "나누기 전에 줄여라" — 양자화(weight-only INT4·FP8)로 모델을 압축하면 더 적은 GPU(또는 단일 GPU)로 서빙해 통신 오버헤드 없이 단순·저비용이 될 때가 많다. 압축으로도 안 들어가거나 지연이 더 필요하면 TP(노드 내), 그래도 부족하면 TP×PP. 처리량은 복제로 수평 확장(작은 단위 모델 여러 벌이 큰 TP 하나보다 효율적일 때 많음). 이 순서 — 양자화 → TP → PP → 복제 — 가 대개 비용효율적이다.

비엔비디아 정직: AWQ·GPTQ·SmoothQuant·페이지드 어텐션은 연구·오픈소스에서 나온 공통 기법으로 vLLM·SGLang도 지원한다. TP/PP도 표준 병렬화다. TRT-LLM의 차별점은 FP8/FP4 텐서코어·트랜스포머 엔진·NVLink 통신·이 기법들의 통합·Triton 서빙이다. 양자화 정확도·병렬 효율은 모델·하드웨어·시점마다 다르니 vLLM/SGLang과 실측 비교(5.15).

5.9.10 흔한 함정

  • TP를 NVLink 도메인 너머로. 매 레이어 all-reduce가 느린 네트워크를 타 병목 → 같은 GPU 수로 더 느림. TP는 노드 내, 초과는 PP(4.14).
  • 저지연인데 PP 위주. PP는 단일 요청 버블로 지연에 불리. 저지연 우선이면 TP 우선, PP는 노드 확장·메모리용.
  • "나누기 먼저, 줄이기 나중". 양자화로 단일/소형 구성에 들어갈 모델을 굳이 큰 TP/PP로 → 불필요한 통신·복잡. 양자화 먼저 검토.
  • regime 무시한 양자화. 큰 배치(컴퓨트 바운드)에 weight-only INT4를 기대 → 활성화 FP16이라 이득 작음. 큰 배치는 FP8 W8A8. 작은 배치 decode는 W4A16.
  • INT8 활성화를 보정 없이 적용. 트랜스포머 활성화 이상치로 정확도 붕괴 → SmoothQuant(이상치 이전) 또는 FP8.
  • 양자화 정확도 미검증. weight-only INT4/FP8도 품질 영향 가능 → 퍼플렉시티·다운스트림으로 검증(5.5). 캘리브레이션 데이터 대표성도(5.4).
  • 엔진을 다른 TP/PP·GPU에서 재사용. 구성·GPU·버전 종속 → 대상 구성에서 재빌드.
  • 총 GPU 계산 착각. 총 GPU = TP×PP(×복제). 매핑이 인터커넥트와 맞는지(4.14) 확인.

5.9.11 연습문제

연습 1 (TP vs PP). 추론에서 TP와 PP가 단일 요청 지연에 미치는 영향이 정반대인 이유를 설명하고, 각각이 어느 인터커넥트에 매핑돼야 하는지와 그 이유를 제시라.

정답

TP는 한 레이어의 계산을 여러 GPU가 동시에 분담하고 결과를 합치므로(매 레이어 all-reduce) 단일 요청의 각 스텝이 빨라짐(지연↓) — 단 통신이 잦아 NVLink 도메인 안(고대역·저지연)이어야 통신이 병목이 안 됨. PP는 레이어를 스테이지로 나눠 요청이 순차로 스테이지를 통과하므로, 한 스테이지가 계산할 때 다른 스테이지는 유휴가 되어(버블) 단일 요청 지연엔 불리 — 대신 통신이 스테이지 경계에서만(드묾)이라 노드 간 IB에 매핑 가능. 매핑 원리(4.14): 잦은 통신(TP)=NVLink 도메인, 드문 통신(PP)=노드 간. 어기면 TP all-reduce가 느린 망을 타 급격히 느려짐.

연습 2 (regime 양자화). 같은 70B 모델을 (a) 단일 사용자 대화형(배치 1, 저지연), (b) 대량 오프라인 요약(큰 배치, 처리량)으로 서빙한다. 각각 어떤 양자화로 시작할지와 이유, 그리고 공통으로 추가할 KV 전략.

정답

(a) weight-only INT4(AWQ/GPTQ, W4A16) — 배치 1 decode는 메모리 바운드(가중치 읽기 병목)라 가중치를 1/4로 줄이면 TPOT·메모리에 큰 이득. 활성화 FP16이라 정확도도 비교적 안전. (b) FP8 W8A8(Hopper+) — 큰 배치는 컴퓨트 바운드라 활성화도 8비트로 줄여 텐서코어 처리량을 끌어올림(트랜스포머는 FP8 적합). 공통: KV 양자화(FP8/INT8) 로 동시성·decode 메모리 추가 절감(특히 (b)의 동시성, (a)의 긴 문맥). 모두 퍼플렉시티·다운스트림으로 검증. (a)는 weight-only가 메모리·메모리 양쪽을 직격, (b)는 컴퓨트가 핵심이라 W8A8.

연습 3 (SmoothQuant). 어떤 팀이 FP8 미지원 GPU에서 INT8 W8A8을 시도했더니 정확도가 무너졌다. 원인(트랜스포머 특유)과 SmoothQuant가 이를 어떻게 해결하는지, 대안(FP8 가능 시)도 설명하라.

정답

원인: 트랜스포머 활성화의 이상치(outlier) — 일부 채널이 매우 큰 값을 가져, INT8 균일 양자화로 이를 담으면 다른 값의 해상도가 저하되거나 클리핑되어 정확도 붕괴(5.5에서 FP8이 유리한 이유). SmoothQuant: 활성화의 이상치 스케일을 수학적으로 동등하게 가중치로 "이전(migrate)" 해(활성화÷s, 가중치×s) 활성화를 평탄하게 만들어 INT8 양자화를 실용화. 활성화·가중치 모두 INT8 W8A8 가능. 대안: FP8 가능 GPU(Hopper+)면 FP8 W8A8 — 부동소수 동적 범위로 이상치를 자연히 담아 SmoothQuant 없이도 트랜스포머에 적합. 모두 검증 필수.

연습 4 (매핑). 16-GPU(노드 2×8-GPU NVLink)에서 70B를 서빙한다. (a) TP=16, PP=1 매핑의 문제, (b) TP=8, PP=2 매핑이 나은 이유, (c) 각 GPU의 가중치·KV 메모리는 어떻게 분산되나.

정답

(a) TP=16은 16장 전체에 텐서 병렬 → 매 레이어 all-reduce가 노드 경계(IB)를 넘음. TP 통신은 잦고 큰데 NVLink보다 느린 IB를 타 통신 병목으로 같은 16장이라도 훨씬 느림. (b) TP=8을 노드 내 NVLink 도메인에, PP=2를 노드 경계 IB에 정렬 → 잦은 TP 통신은 NVLink(빠름), 드문 PP 경계 P2P는 IB(견딤) → 4.14 원리 충족. (c) 가중치: TP=8로 각 레이어가 8등분(노드 내), PP=2로 레이어를 두 노드가 절반씩 → GPU당 ≈ 1/16 가중치. KV: TP가 헤드를 8등분 → GPU당 KV도 ≈ 1/8(스테이지 내), 레이어는 PP로 분산. 병렬이 가중치·KV 예산을 함께 분산.

연습 5 (순서 설계). 새 LLM 서비스의 인프라를 정한다. "양자화 → TP → PP → 복제"의 순서로 의사결정을 펼치고, 각 단계로 넘어가는 조건을 명시하라.

정답

① 양자화로 줄이기: weight-only INT4(대화형)·FP8(처리량)로 모델을 압축 → 단일 GPU(또는 작은 TP)에 들어가면 통신 0으로 가장 단순·저비용. 정확도 검증 통과가 조건. ② TP(노드 내): 압축해도 한 GPU 메모리 초과거나 지연을 더 줄여야 하면 NVLink 도메인 안에서 TP. 조건: 모델이 노드 하나엔 들어감, 저지연 필요. ③ TP×PP: 모델이 노드 하나도 초과하면 TP(노드 내)×PP(노드 간). 조건: 단일 노드 메모리 초과. ④ 복제(수평 확장): 지연·메모리는 됐고 처리량을 더 원하면 모델 단위(단일 GPU 또는 작은 TP)를 여러 벌 기동해 요청 분산. 각 단계는 정확도·p99·tokens/s·$/토큰을 실측해 다음으로 넘어갈지 판단. 핵심: 통신을 늘리기 전에 압축·복제로 푸는 것이 대개 효율적.

5.9.12 요약 · 다음 장

  • 한 GPU로 부족하면 병렬화(메모리·지연) 또는 양자화(압축)로 푼다. 추론 병렬은 학습과 달라 TP=지연 단축, PP=노드 확장, DP=복제가 주 동기.
  • TP는 매 레이어 가중치를 분산해 all-reduce — 통신이 잦아 NVLink 도메인 안이어야 하고, 메모리·지연을 둘 다 줄인다. PP는 레이어를 스테이지로 나눠 P2P — 통신이 드물어 노드 간 가능하나 단일 요청 버블로 지연 불리. TP×PP는 TP=NVLink·PP=IB 매핑(4.14).
  • LLM 양자화는 regime이 정한다: decode/작은 배치는 weight-only INT4(AWQ·GPTQ, W4A16) 로 가중치 읽기 병목 직격, prefill/큰 배치는 FP8 W8A8로 컴퓨트 처리량, INT8 활성화는 SmoothQuant(이상치 이전), 그리고 KV 양자화를 독립 조합.
  • 의사결정 순서: 양자화로 줄이기 → TP(노드 내) → PP(노드 간) → 복제(수평). 통신을 늘리기 전에 압축·복제로 푸는 것이 대개 효율적. 모든 정밀도·병렬은 정확도·성능 실측.
  • 정직: TP/PP·양자화 인자·지원은 버전·모델 의존, AWQ/GPTQ/SmoothQuant는 통합된 외부 방법, 엔진은 구성 종속(재빌드).

이어서(번호는 이 장 끝에 붙지만 내용은 이 자리에 속한다) 5.9.13 multi-LoRA 서빙 — 커스터마이즈 변형마다 모델을 복제하지 않고 베이스 하나로 여러 어댑터를 서빙하는 법 — 을 본 뒤 5.10로 이어진다.

5.9.13 multi-LoRA 서빙 — 베이스 하나, 어댑터 여럿

6.4에서 LoRA로 태스크·부서별 변형을 만들었다(가중치 변화 $BA$, 저랭크 $r$). 6.7(NIM)은 "한 베이스 LLM에 부서별 LoRA 어댑터를 적재해 요청마다 해당 어댑터를 적용"한다고 예고했다 — 그 메커니즘이 이것이다. 번호는 이 장(5.9)의 끝에 붙었지만, 내용은 5.9.6(양자화) 바로 다음 자리에 속한다 — TP/PP·양자화가 "한 모델을 어떻게 굴릴까"라면, multi-LoRA는 "여러 변형을 어떻게 한 배포로 굴릴까"다.

문제: 부서·태스크마다 LoRA로 파인튜닝한 변형이 N개 있다고 하자. 순진하게는 변형마다 병합된 모델 전체를 배포(6.4의 $W \leftarrow W + (\alpha/r) BA$ 병합) — 하지만 그러면 N개 배포가 거대한 베이스 가중치를 N번 중복 저장·서빙한다(70B 모델이면 N배의 GPU 메모리).

순진한 접근: 변형마다 병합된 모델 전체 배포 N개 배포 = 베이스 가중치 N번 중복 (어댑터는 원래 베이스 대비 MB급인데 GB급 낭비) multi-LoRA: 베이스 하나 + 어댑터 여럿 베이스 가중치는 GPU에 1벌만 상주 어댑터(A·B, 저랭크 r)는 각각 수 MB — 여러 개를 함께 캐시 요청마다 '이 요청은 어댑터 k' 지정 → 그 요청 경로에만 BA 저랭크 업데이트 적용 한 배치 안에 서로 다른 어댑터를 쓰는 요청이 섞여도(mixed batch) 처리 가능

메커니즘 개략: 베이스 가중치 $W$는 공유 상주하고, 어댑터별 저랭크 행렬 $(A_k, B_k)$를 별도로 GPU 메모리에 캐시해 둔다. 순전파에서 요청이 어댑터 $k$를 지정하면 $h = Wx + (\alpha_k/r_k)\,B_k A_k x$(6.4 순전파 식과 동일 구조)를 그 요청 경로에만 적용 — 베이스 행렬곱은 배치 전체가 공유하고, 저랭크 업데이트만 요청별로 다르게 적용하는 방식이다. TensorRT-LLM은 이를 LoRA 플러그인/런타임 어댑터 캐시 기능으로 지원한다(정확한 API·플래그명은 버전 의존, 문서 확인).

트레이드오프:

항목순진한 배포(변형마다 전체 병합)multi-LoRA
메모리베이스 × N (거대)베이스 × 1 + 어댑터 × N (어댑터는 MB급)
새 어댑터 추가새 배포 전체 필요어댑터만 캐시에 추가(경량이다)
배치 효율변형별로 배치가 분할됨(테넌트당 낮은 동시성)테넌트를 한 배치로 합쳐 GPU 활용률↑(mixed batch)
요청당 오버헤드없음(병합 완료 상태)저랭크 행렬곱 추가(보통 작음, $r \ll d$)
어댑터 구성 제약없음(자유)엔진 빌드 시 정한 최대 랭크·타깃 모듈 안에서만(버전 의존) — 그 밖 구성의 어댑터는 재빌드 필요할 수 있음

견해: 어댑터 수(테넌트·태스크)가 많고 각자 트래픽이 낮을수록(전형적인 SaaS 멀티테넌시) multi-LoRA의 메모리·배치 효율 이득이 커진다. 반대로 어댑터가 하나뿐이거나 트래픽이 압도적으로 크면, 병합해 전체를 배포하는 쪽이 단순하고 요청당 오버헤드도 없다 — 5.9.9의 "나누기/줄이기 전에 단순한 선택부터" 원칙과 같은 결.

흔한 함정: 임의의 LoRA 어댑터나 재빌드 없이 자유롭게 섞을 수 있다고 가정하는 것 — 실제로는 엔진을 빌드할 때 정한 최대 랭크·타깃 모듈 집합을 벗어나는 어댑터는 못 쓰거나 재빌드가 필요할 수 있다(버전·구현 의존, 확인 필요). 서빙 전에 후보 어댑터들의 랭크·타깃 모듈이 엔진 설정 범위 안인지 확인한다.

정직: multi-LoRA 서빙의 정확한 API·플러그인명·지원 범위(동시 캐시 가능한 어댑터 수, 핫스왑 지연 등)는 TRT-LLM 버전·모델마다 다르다 — 이 절은 원리(베이스 공유 + 저랭크 어댑터 캐시)를 가르치고, 정확한 설정은 그 버전 문서로 확인한다. vLLM·SGLang 등 오픈소스 서버도 유사한 multi-LoRA 서빙을 지원한다(5.15, 실측 비교 권장).

다음 장: 5.10 TensorRT-LLM IV — speculative decoding. decode가 메모리 바운드(연산 여유 있음)라는 점을 역이용해, 작은 초안 모델로 여러 토큰을 추측하고 큰 모델로 한 번에 검증해 TPOT를 줄이는 기법 — draft·verify 구조, 수용률, self-speculative·Medusa류를 실습으로 본다. 이로써 TRT-LLM 묶음(5.7~5.10)을 마무리한다.