[LLMSO] LLM Serving 병목을 찾는 법

xgro·2026년 8월 22일

LLMSO

목록 보기
5/10
post-thumbnail

📌 Notice

LLM Serving and Optimization Study (=LLMSO)
직접 실습을 통해 LLM 서비스 제공 및 최적화에 대한 지식에 대한 학습 및 실습 내용을 정리한 블로그입니다.

CloudNet@에서 스터디를 진행하고 있습니다.

EKS 관련 이전 스터디 내용은 아래 링크를 통해 확인할 수 있습니다.

📌 Intro

LLM을 서비스로 제공할 때는 모델이 답변을 생성할 수 있는지만으로 충분하지 않습니다.

사용자가 첫 Token을 보기까지 얼마나 기다려야 하는지,
전체 답변이 끝날 때까지 얼마나 걸리는지,
요청이 몰렸을 때도 서비스를 유지할 수 있는지,
그리고 그 과정에 GPU 비용이 얼마나 드는지를 함께 생각해야 합니다.

CH5에서는 이 문제를 다음 질문으로 좁혀서 살펴봅니다.

LLM Serving 요청은 어느 단계에서 병목이 생기며,
그 병목은 Compute·Memory·Interconnect 중 무엇과 관련이 있는가?



🧭 Overview

🎯 이번 챕터에서 확인할 것

  • 왜 LLM Serving 최적화가 필요한가
  • TTFT와 E2E Latency는 어떻게 다른가
  • GPU Spec에서 Compute·Memory·Interconnect를 어떻게 읽는가
  • 모델 Weight와 KV Cache가 GPU Memory를 어떻게 사용하는가
  • Prefill과 Decode는 어떤 실행 특성을 가지는가
  • Arithmetic Intensity와 Roofline Model은 병목 분석에 어떻게 쓰이는가
  • 다른 Accelerator와 Memory Wall을 어떤 기준으로 비교하는가

🧩 CH03·CH05·CH06의 연결

CH03: 요청이 Serving System 안에서 어떻게 처리되는가?
          ↓
CH05: 그 과정에서 병목은 어디서 생기는가?
          ↓
CH06: 병목을 줄이기 위해 어떤 최적화 기법을 쓰는가?

CH03에서 요청의 생명주기와 Serving 구성요소를 살펴봤다면, CH05에서는 각 단계가 어떤 자원을 사용하고 어디에서 제한될 수 있는지
확인합니다. CH06에서는 그 진단 결과를 바탕으로 Batching, Attention, Quantization, Prefix Caching 같은 최적화 기법으로 이어갑니다.

🧪 학습 흐름

  1. 사용자 경험·비용·확장성 관점에서 최적화 목표를 정의합니다.
  2. GPU Spec을 Compute·Memory·Interconnect·Power 관점으로 읽습니다.
  3. PCIe·NVLink·NVSwitch·InfiniBand의 통신 범위를 구분합니다.
  4. 모델 로딩 과정과 Weight Memory를 추정합니다.
  5. KV Cache와 실행 중 GPU Memory를 계산합니다.
  6. Arithmetic Intensity와 Roofline Model로 병목을 해석합니다.
  7. Prefill과 Decode의 Shape·병목 차이를 연결합니다.
  8. Other Accelerator와 Memory Wall을 운영 관점에서 비교합니다.
  9. 선택적으로 멤버 운영 사례를 읽고 CH06의 최적화 기법으로 연결합니다.



🚀 Step 01. 왜 LLM Serving을 최적화하는가

🎯 이 Step의 질문

모델이 답변을 생성할 수 있다면, 왜 LLM Serving System을 따로 최적화해야 할까?

LLM을 처음 공부할 때는 다음 코드만 실행하면 서비스가 완성될 것처럼 느껴질 수 있습니다.

response = model.generate(prompt)

하지만 실제 사용자가 만나는 것은 generate() 함수가 아니라, 요청을 받고 모델을 실행하고 답변을 전달하는 전체 시스템입니다.

이번 Step에서는 아직 GPU를 벤치마크하지 않습니다.

먼저 무엇을 빠르게 만들어야 하는지, 그리고 무엇을 기준으로 Serving을 평가해야 하는지부터 정리합니다.

💡 Inference와 Serving은 다르다

Inference는 모델이 입력을 계산하고 다음 Token을 생성하는 과정입니다.

Serving은 그 추론을 사용자에게 제공하기 위해 필요한 주변 시스템까지 포함합니다.

Inference
└─ 입력을 모델에 전달하고 출력 Token을 계산하는 과정

Serving
└─ 요청 수신
   ├─ 입력 검증과 요청 관리
   ├─ 모델과 Weight 준비
   ├─ 대기열과 Scheduling
   ├─ Inference 실행
   └─ 생성 결과 전달

따라서 모델이 빠르게 Token을 생성하더라도 다음 상황에서는 사용자가 서비스를 느리다고 느낄 수 있습니다.

  • 요청이 Queue에서 오래 기다리는 경우
  • 모델을 실행할 GPU Memory가 부족한 경우
  • 첫 Token을 만들기까지 입력 처리 시간이 긴 경우
  • 전체 응답이 생성될 때까지 결과를 전달하지 않는 경우
  • Peak Traffic에서 처리 용량보다 요청이 많이 들어오는 경우

LLM Serving 최적화는 모델의 연산 속도만 높이는 일이 아니라,
요청의 전체 생명주기에서 병목을 찾아 줄이는 일입니다.

🧩 요청은 어떤 흐름으로 처리될까?

LLM Serving 요청을 단순화하면 다음과 같은 흐름으로 볼 수 있습니다.

사용자 요청
   ↓
API 수신
   ↓
Queue와 Scheduling
   ↓
입력 처리와 Model Execution
   ↓
첫 Token 생성
   ↓
남은 Token 생성
   ↓
전체 응답 전달

이 흐름을 기준으로 보면 “모델이 느리다”는 말만으로는 원인을 충분히 설명할 수 없습니다. 요청 대기, 모델 실행, 응답 생성 중 어디에서 시간이 사용되었는지를 나눠서 봐야 합니다.

👤 첫 응답과 전체 응답은 다르다

LLM 응답 시간은 하나의 숫자로만 보지 않는 것이 좋습니다.

요청 시작 ───────── 첫 Token ───────────── 응답 완료
             TTFT                    E2E Latency

TTFT: 첫 Token까지의 시간

TTFT(Time To First Token)는 사용자가 요청을 보낸 뒤 첫 번째 Token을 확인하기까지 걸리는 시간입니다.

TTFT가 길면 사용자는 다음처럼 느낄 수 있습니다.

아직 응답이 시작되지 않았네.

Queue에서 오래 기다리거나, 긴 입력을 처리하는 Prefill 시간이 길면 첫 Token이 늦어질 수 있습니다.

E2E Latency: 전체 응답이 끝날 때까지의 시간

여기서는 요청 시작부터 전체 응답이 완료될 때까지의 시간을 E2E(End-to-End) Latency라고 부르겠습니다.

첫 Token은 빨리 도착했지만 이후 Token 생성이 오래 걸리면, TTFT는 괜찮아도 E2E Latency는 길 수 있습니다.

따라서 다음 두 문제는 구분해야 합니다.

  • 첫 응답이 늦은가? → Queue, Scheduling, 입력 처리와 TTFT를 확인합니다.
  • 첫 응답은 빠르지만 답변이 늦게 끝나는가? → 이후 Token 생성과 전체 응답 전달을 확인합니다.

1. 고객 경험: 빠르기만 하면 충분할까?

원문은 LLM Serving 최적화가 중요한 첫 번째 이유로 Customer Experience를 제시합니다.

응답 지연이 길어질수록 사용자의 만족도가 떨어질 수 있기 때문입니다.
다만 지연시간과 만족도의 관계는 단순한 직선이 아닙니다.

  • 20초에서 1초로 줄이는 변화는 크게 체감될 수 있습니다.
  • 이미 충분히 빠른 0.1초에서 0.01초로 줄이는 변화는 체감이 작을 수 있습니다.

이 수치는 이번 환경에서 측정한 결과가 아니라, 원문이 설명을 위해 제시한 사고 실험입니다.

중요한 것은 특정 숫자 자체보다 사용자가 체감하는 개선의 크기와 시스템 비용을 함께 봐야 한다는 점입니다.

또 다른 축은 모델의 응답 품질입니다. 일반적으로 같은 계열의 모델에서는 더 큰 모델이 더 높은 품질을 보일 가능성이 있지만, 더 많은 GPU Memory와 처리 시간을 요구할 수 있습니다.

결국 Serving 설계는 다음 세 요소 사이의 균형을 찾는 문제입니다.

응답 품질
   ↕
지연시간 ─── 처리량 ─── 비용

“가장 빠른 모델”을 선택하는 것이 언제나 정답은 아닙니다.

사용자가 필요로 하는 품질과 지연시간을 만족하면서, 감당할 수 있는 비용으로 처리하는 것이 목표입니다.

2. 비용 효율성: 추론은 요청이 들어올 때마다 발생한다

모델을 한 번 학습하는 비용과, 배포한 모델을 계속 실행하는 비용은 성격이 다릅니다.

Training
└─ 주로 초기 투자와 재학습 비용

Inference
└─ 배포 후 요청과 상호작용이 발생할 때마다 계속 발생하는 운영 비용

실제 서비스에서 추론 요청이 계속 증가하고, AI Agent나 복잡한 Workflow에서는 한 번의 작업에도 여러 LLM·Embedding 호출이 발생할 수 있으므로 추론 비용 관리가 중요하다고 설명합니다.

Serving 비용은 단순히 GPU의 시간당 가격만으로 결정되지 않습니다.

  • 모델의 Parameter 수와 Weight Precision
  • 모델을 담기 위한 GPU Memory 용량
  • 동시에 처리하는 요청 수
  • 요청이 몰리는 Peak Traffic
  • 요청을 처리하기 위해 미리 확보한 Model Replica 수
  • GPU가 유휴 상태로 남는 시간

같은 하드웨어에서 더 많은 요청을 처리할 수 있다면 필요한 Replica 수를 줄일 수 있습니다. 또는 동일한 요구사항을 더 저렴한 GPU에서 만족할 수 있다면 하드웨어 비용을 줄일 수 있습니다.

다만 이 글에서는 특정 GPU 가격이나 추론 비용을 직접 측정하지 않습니다.
따라서 여기서 말하는 비용 개선은 원리와 설계 방향이며, 실제 비용 절감률로 해석하면 안 됩니다.

3. 확장성·Peak Load·실현 가능성

평균 트래픽을 처리할 수 있다고 해서 서비스가 항상 안정적인 것은 아닙니다.

장애와 지연은 평균보다 Peak Traffic에서 먼저 드러나는 경우가 많습니다.

요청 증가
   ↓
Queue 증가
   ↓
TTFT와 전체 지연시간 증가
   ↓
Timeout 또는 재시도
   ↓
추가 요청 증가

원문은 Black Friday와 같은 상황에서 수요가 평소보다 400% 이상 증가할 수 있는 사례를 제시합니다. 이 역시 우리 환경에서 측정한 트래픽 수치가 아니라 Peak Load의 위험을 설명하기 위한 원문 사례입니다.

Peak Load를 처리하려면 GPU 연산 성능만이 아니라 다음 조건을 함께 봐야 합니다.

  • Model Replica를 얼마나 빠르게 늘릴 수 있는가?
  • GPU Memory에 모델과 동시 요청 상태를 함께 담을 수 있는가?
  • Queue가 얼마나 쌓일 때 요청을 거절하거나 지연시킬 것인가?
  • Autoscaling과 Model Loading에 걸리는 시간은 얼마인가?
  • 모델이 너무 커서 여러 GPU 또는 여러 노드로 나뉘어야 하는가?
  • 배포하려는 리전에서 원하는 GPU를 실제로 확보할 수 있는가?

따라서 Serving 최적화는 성능과 비용뿐 아니라,
어떤 하드웨어 환경에서도 서비스를 실제로 배포할 수 있는가라는
실현 가능성의 문제이기도 합니다.

⚖️ 최적화는 Trade-off를 조정하는 일이다

최적화는 모든 지표를 동시에 무조건 개선하는 마법이 아닙니다.
한 지표를 개선하면 다른 지표에 비용이 생길 수 있습니다.

목표기대하는 변화함께 확인할 점
TTFT 단축첫 응답을 더 빨리 표시Queue, 입력 처리, GPU Memory
전체 지연시간 단축답변 완료 시점을 앞당김Decode 시간과 출력 Token 수
처리량 증가같은 시간에 더 많은 요청 처리동시성, Queue, GPU 사용률
더 큰 모델 사용응답 품질 향상 가능Weight 용량, 비용, 지연시간
더 저렴한 GPU 사용시간당 비용 절감 가능Memory, Bandwidth, Interconnect

그러므로 최적화를 시작하기 전에 최소한 다음 질문을 정해야 합니다.

  • 사용자는 첫 Token을 언제까지 받아야 하는가?
  • 전체 답변은 언제까지 완료되어야 하는가?
  • 동시에 몇 개의 요청을 처리해야 하는가?
  • 모델 품질, 지연시간, 처리량, 비용 중 무엇을 우선하는가?
  • 평상시가 아니라 Peak Traffic에서도 이 조건을 만족해야 하는가?

🧠 실행 전에 생각해보기

다음 상황을 보고 가장 먼저 확인할 지표를 예상해봅니다.

  1. 첫 Token이 늦게 나온다.
  2. 첫 Token은 빠르지만 전체 답변이 늦게 끝난다.
  3. 평소에는 빠르지만 요청이 몰리면 급격히 느려진다.

예상 답변은 다음과 같이 정리할 수 있습니다.

상황먼저 볼 관점
첫 Token이 늦음Queue, Scheduling, 입력 처리, TTFT
전체 답변이 늦음Decode, 출력 Token 수, E2E Latency
Peak에서만 느림Queue, 동시성, GPU Memory, Replica와 Autoscaling

이 표는 아직 측정 결과가 아니라, 다음 Step에서 검증할 첫 번째 가설입니다.

✅ Step 01의 핵심

LLM Serving 최적화는 모델의 계산만 빠르게 만드는 일이 아닙니다.

  1. Customer Experience: 첫 응답과 전체 응답을 사용자가 어떻게 느끼는가
  2. Cost Efficiency: 요청이 늘어날수록 발생하는 추론 비용을 감당할 수 있는가
  3. Scalability·Peak Load·Feasibility: 트래픽이 몰리거나 GPU가 부족해도 서비스를 유지할 수 있는가

이 세 가지 질문을 함께 봐야 “좋은 Serving”을 정의할 수 있습니다.
다음 Step에서는 이 요구사항을 실제 하드웨어 관점으로 옮겨서,
Compute·Memory·Interconnect 중 어디가 병목이 될 수 있는지 살펴봅니다.



🚀 Step 02. GPU Spec은 무엇을 읽어야 하는가

🎯 이 Step의 질문

TFLOPS가 높은 GPU가 항상 좋은 LLM Serving GPU일까?

결론부터 말하면 그렇지 않습니다.

LLM Serving에서는 GPU의 연산 성능만 보는 순간 중요한 조건을 놓칠 수 있습니다.

모델을 GPU에 올릴 수 있는지,
Weight와 KV Cache를 얼마나 빠르게 읽을 수 있는지,
여러 GPU가 필요한 경우 서로 얼마나 빠르게 통신하는지를 함께 봐야 합니다.

이번 Step에서는 GPU 제품을 추천하지 않습니다.
대신 사양표를 읽고 워크로드의 병목 가설을 세우는 방법을 익힙니다.

💡 GPU Spec을 네 가지 질문으로 바꾸기

GPU 사양표를 처음 보면 FP16, FP8, TFLOPS, GB/s 같은 숫자가 한꺼번에 나옵니다.
숫자를 외우기보다 다음 질문으로 바꿔 읽는 편이 쉽습니다.

질문연결되는 SpecServing에서 확인하는 것
계산을 얼마나 빠르게 하는가?Compute, FLOPS, Tensor Core, PrecisionMatrix Multiplication과 Attention 처리
모델을 담을 수 있는가?GPU Memory Capacity, VRAMWeight와 KV Cache의 수용 가능 여부
데이터를 얼마나 빨리 공급하는가?Memory BandwidthHBM에서 연산 유닛으로 Weight·Activation 이동
여러 GPU가 협력할 수 있는가?PCIe, NVLink, NVSwitch, InfiniBandTensor Parallelism과 Multi-node 통신

여기에 데이터센터 관점에서는 Power Consumption도 추가해야 합니다.

같은 처리량을 더 적은 전력으로 달성할 수 있는지는 운영 비용과 랙 배치 가능한 GPU 수에 영향을 줍니다.

1. Compute: 오븐의 화력

FLOPS(Floating-point Operations Per Second)는 1초에 수행할 수 있는 부동소수점 연산 횟수를 나타냅니다. TeraFLOPS는 1초에 1조 단위의 연산을 의미합니다.

LLM에서는 주로 Matrix Multiplication, Attention, MLP 같은 연산의 처리 능력과 연결됩니다.

다만 다음 조건에서는 Compute 수치가 높아도 GPU가 계산 유닛을 충분히 사용하지 못할 수 있습니다.

  • Batch가 작고 Decode가 한 Token씩 진행되는 경우
  • 연산에 필요한 데이터를 GPU Memory에서 충분히 빨리 공급하지 못하는 경우
  • 모델이 여러 GPU로 나뉘어 GPU 간 통신을 기다리는 경우

즉, 높은 TFLOPS는 가능한 계산 속도이지 모든 Serving 요청에서 실제로 달성하는 속도는 아닙니다.

2. Memory: 냉장고와 재료 공급 속도

GPU Memory는 두 가지 관점으로 나눠야 합니다.

Memory Capacity

Memory Capacity는 GPU에 데이터를 얼마나 많이 담을 수 있는지를 뜻합니다.

  • Model Weight를 담을 수 있어야 합니다.
  • 요청이 늘면 KV Cache도 필요합니다.
  • 실행 중 Activation과 임시 Buffer를 위한 공간도 남겨야 합니다.

모델 Weight만 겨우 들어가는 GPU는 실제 Serving에서 여유가 부족할 수 있습니다.

Memory Bandwidth

Memory Bandwidth는 GPU Memory에서 데이터를 얼마나 빠르게 읽고 쓸 수 있는지를 나타냅니다.

특히 Decode에서는 매 Token을 생성할 때 Weight와 KV Cache를 반복적으로 읽어야 하므로,
단순한 Compute 성능보다 Memory Bandwidth가 더 중요한 병목이 될 수 있습니다.

3. Interconnect: GPU 사이의 도로

하나의 GPU로 모델을 담을 수 없다면 여러 GPU를 함께 사용해야 합니다.
이때 GPU 수만 늘린다고 성능이 자동으로 선형 증가하지는 않습니다.

Tensor Parallelism을 사용하면 GPU 사이에 다음 데이터가 오갑니다.

  • Activation
  • Partial Result
  • Layer 사이의 Synchronization 정보

따라서 GPU 간 통신 경로가 느리면, 각 GPU의 Compute 성능이 남아 있어도
전체 Serving은 통신을 기다리게 됩니다.

Interconnect의 상세한 종류와 topology는 다음 Step에서 따로 다룹니다.
이번 Step에서는 “GPU를 여러 개 사용한다면 연결 방식도 Spec의 일부”라는 점만 기억하면 됩니다.

4. Power: 실제 환경에 배치할 수 있는가

GPU의 전력 소비는 보통 Watt 또는 TDP로 표현합니다.

전력은 단순히 전기요금만의 문제가 아닙니다.

  • 랙에 몇 개의 GPU를 배치할 수 있는가
  • 전원 공급 장치가 감당할 수 있는가
  • 냉각 시스템이 열을 제거할 수 있는가
  • 같은 전력 예산에서 처리량을 얼마나 낼 수 있는가

따라서 대규모 운영에서는 GPU의 절대 성능뿐 아니라 Performance per Watt도 중요한 판단 기준입니다.

🧾 원문 GPU 비교표 읽기

H100 SXM과 H100 NVL을 비교한 표가 있습니다.

이를 “어느 GPU가 무조건 우수한가”가 아니라 “어떤 축에서 차이가 나는가”를 읽는 예시로 사용하겠습니다.

항목H100 SXMH100 NVL
GPU Memory80 GB94 GB
GPU Memory Bandwidth3.35 TB/s3.9 TB/s
FP16 Tensor Core1,979 teraFLOPS1,671 teraFLOPS
Interconnect 예시NVLink 900 GB/sNVLink 600 GB/s

이 표만 보면 H100 SXM은 Compute와 Interconnect 측면에서,
H100 NVL은 Memory Capacity와 Bandwidth 측면에서 강점이 있는 것처럼 읽을 수 있습니다.

하지만 이것만으로 Serving 성능을 단정할 수는 없습니다.

  • 실제 Workload의 Arithmetic Intensity가 무엇인지
  • 모델이 한 GPU에 들어가는지
  • Batch와 Context Length가 어느 정도인지
  • 여러 GPU 간 통신이 얼마나 자주 필요한지
  • 비용과 전력 조건이 어떤지

를 함께 확인해야 합니다.


🍕 피자 가게 비유로 다시 보기

Serving 관점으로 정리하면 다음과 같습니다.

GPU 요소피자 가게LLM Serving에서 의미
Compute오븐의 화력계산을 수행하는 속도
Memory Capacity재료를 보관하는 냉장고Weight와 KV Cache 저장 공간
Memory Bandwidth재료를 오븐으로 옮기는 속도연산 유닛으로 데이터 공급
Interconnect주방 사이의 통로GPU 간 데이터 전달
Power주방의 전력·냉각 한도실제 배치 가능한 처리 용량

냉장고가 작으면 모델을 올릴 수 없습니다.
오븐이 아무리 강해도 재료가 늦게 오면 오븐은 놀게 됩니다.
주방 사이의 통로가 좁으면 여러 오븐을 사용해도 서로 결과를 전달하는 데 시간이 걸립니다.

🧠 실행 전에 생각해보기

다음 상황에서 먼저 볼 Spec을 예상해봅니다.

  1. 모델 Weight가 GPU Memory에 들어가지 않는다.
  2. 모델은 올라가지만 Decode 처리량이 낮다.
  3. 여러 GPU로 모델을 나눴더니 통신 대기시간이 커졌다.
  4. GPU를 충분히 확보했지만 랙의 전력·냉각 한도를 초과한다.
상황먼저 볼 Spec
모델이 들어가지 않음Memory Capacity
Decode 처리량이 낮음Memory Bandwidth와 Batch
GPU 간 통신이 느림Interconnect와 Topology
배치·냉각 한도 초과Power와 Performance per Watt

이 표는 아직 GPU를 직접 측정한 결과가 아니라,
다음 Step에서 사용할 병목 가설을 세우는 기준표입니다.

✅ Step 02의 핵심

LLM Serving GPU를 고를 때는 다음 네 축을 함께 봐야 합니다.

Compute
+ Memory Capacity
+ Memory Bandwidth
+ Interconnect
+ Power

특히 “TFLOPS가 높다”는 한 가지 사실만으로는 모델이 올라가는지,
Decode가 빠른지, Multi-GPU Serving이 효율적인지 알 수 없습니다.

다음 Step에서는 이 중 Interconnect를 더 자세히 살펴봅니다.

PCIe·NVLink·NVSwitch·InfiniBand가 각각 어느 통신 범위를 담당하는지,
그리고 GPU를 늘려도 성능이 늘지 않을 수 있는 이유를 확인하겠습니다.



🚀 Step 03. 여러 GPU는 어떻게 연결되는가

🎯 이 Step의 질문

GPU를 여러 개 사용하면 성능도 GPU 개수만큼 늘어날까?

모델이 너무 크거나 한 GPU의 처리량이 부족하면 여러 GPU를 함께 사용할 수 있습니다. 하지만 여러 GPU는 하나의 큰 GPU처럼 자동으로 동작하지 않습니다.

GPU 사이에서 Activation, Partial Result, Synchronization 정보가 계속 이동하기 때문입니다.

그래서 Multi-GPU Serving에서는 GPU의 개수뿐 아니라
GPU 사이의 통신 경로와 대역폭을 함께 봐야 합니다.

💡 Intra-node와 Inter-node

먼저 GPU가 어디에 있는지를 구분합니다.

Intra-node
└─ 같은 서버 안의 GPU 사이 통신
   ├─ PCIe
   ├─ NVLink Bridge
   └─ NVLink + NVSwitch

Inter-node
└─ 서로 다른 서버의 GPU 사이 통신
   ├─ InfiniBand
   ├─ RoCE
   └─ RDMA / GPUDirect RDMA

일반적으로 같은 서버 안의 전용 GPU 연결이 서버 사이의 네트워크보다 짧고 빠릅니다.

모델을 여러 노드로 나눌수록 성능뿐 아니라 운영 복잡도도 커질 수 있습니다.

1. PCIe: 호환성이 좋은 기본 경로

PCIe는 일반적인 서버 확장 슬롯을 통해 GPU와 CPU 또는 GPU 사이를 연결합니다.

  • 다양한 서버와 호환되기 쉽습니다.
  • 비용과 구성 난이도가 비교적 낮습니다.
  • GPU 간 통신이 많지 않은 독립적인 모델 배치에는 적합할 수 있습니다.
  • Tensor Parallelism처럼 GPU 간 통신이 잦은 구조에서는 병목이 될 수 있습니다.

중요한 점은 “PCIe가 나쁘다”가 아니라 워크로드의 통신량과 맞는가입니다.

각 GPU에서 서로 독립적인 모델을 실행한다면 통신이 적기 때문에 PCIe만으로도 충분할 수 있습니다.

NVLink Bridge는 PCIe 폼팩터의 GPU 일부를 더 빠른 전용 링크로 연결하는 구성입니다.

이 장의 H100 예시에서는 두 GPU를 NVLink Bridge로 연결하는 구성과,
네 GPU를 구성할 때 모든 GPU 쌍이 같은 경로를 갖지는 않는다는 점을 설명합니다.

이 구조를 읽을 때는 다음을 확인해야 합니다.

  • 몇 개의 GPU가 실제 NVLink로 연결되는가?
  • 연결되지 않은 GPU 사이의 통신은 어디로 우회하는가?
  • Tensor Parallelism이 어느 GPU 쌍 사이에서 동작하는가?

GPU가 네 개라는 사실보다 통신이 필요한 GPU들이 실제로 어떤 링크로 연결되어 있는지가 더 중요합니다.

3. NVLink와 NVSwitch: 여러 GPU의 통신 경로 확장

NVLink는 NVIDIA GPU 사이의 고속 연결이고,
NVSwitch는 여러 NVLink GPU를 스위치 구조로 연결해 통신 경로를 확장합니다.

이를 단순화하면 다음처럼 볼 수 있습니다.

GPU A ─┐
GPU B ─┼─ NVSwitch ─┼─ GPU C
GPU D ─┘            └─ GPU E

전용 스위치가 있으면 GPU 사이의 통신 경로를 더 균일하게 설계할 수
있습니다. 대신 전용 하드웨어 비용과 시스템 구성 복잡도가 증가합니다.

단일 노드의 PCIe·NVLink·NVSwitch와 노드 간 InfiniBand/RDMA 경로 비교

4. Inter-node: InfiniBand와 RDMA

한 서버에 담을 수 있는 GPU 수에는 물리적·전력·냉각 제약이 있습니다.
모델이 더 커지면 여러 서버에 걸쳐 모델을 나눌 수 있고, 이때
InfiniBand나 RoCE 같은 네트워크와 RDMA가 중요해집니다.

RDMA(Remote Direct Memory Access)는 CPU의 개입을 줄이고 다른 노드의
메모리에 직접 접근하는 방식입니다. GPU Serving에서는 GPUDirect RDMA와
같은 기술이 GPU 간 데이터 이동을 줄이는 데 사용될 수 있습니다.

다만 Inter-node Serving은 다음 비용을 함께 가져옵니다.

  • 네트워크 지연시간
  • 통신 경로와 장애 지점 증가
  • 노드별 GPU·메모리·소프트웨어 버전 관리
  • 모델 분할과 배포 복잡도

그래서 가능한 경우 먼저 한 노드 안에서 모델을 구성하고, 모델 크기나
처리량 요구사항 때문에 필요한 경우에만 여러 노드로 확장하는 방향을
검토합니다.

🧾 통신 속도 비교표 읽기

이 장의 자료에는 H100 구성에 대한 다음과 같은 예시가 있습니다.

Setup자료에서 제시한 예시 대역폭
같은 노드, NVLink/NVSwitch900 GB/s
같은 노드, NVLink Bridge600 GB/s
같은 노드, PCIe128 GB/s
노드 간 연결50 GB/s

이 숫자를 현재 모든 환경에 적용하면 안 됩니다. 링크 수, 방향성,
토폴로지, 실제 메시지 크기, 통신 패턴에 따라 관측값이 달라집니다.
여기서 중요한 결론은 절대 숫자보다 같은 노드의 전용 링크와 노드 간
네트워크가 서로 다른 병목을 가진다
는 점입니다.

🧠 구성 선택 연습

다음 세 가지 상황에서 어떤 구성을 먼저 검토할지 생각해봅니다.

  1. 작은 모델 두 개를 한 서버의 서로 다른 GPU에서 독립적으로 실행한다.
  2. 하나의 큰 모델을 같은 서버의 여러 GPU로 나누고 Layer 사이에서 계속 통신한다.
  3. 단일 서버에 모델이 들어가지 않아 여러 서버로 Sharding한다.
상황먼저 검토할 연결
독립적인 모델 실행PCIe도 가능한지 확인
같은 노드의 Tensor ParallelismNVLink·NVSwitch와 Topology 확인
여러 서버의 Model ShardingInfiniBand/RoCE, RDMA와 네트워크 구성 확인

정답은 GPU 수가 아니라 통신 패턴에서 결정됩니다.

✅ Step 03의 핵심

Multi-GPU Serving에서 기억할 문장은 다음과 같습니다.

GPU를 추가하면 Compute와 Memory Capacity는 늘어날 수 있지만,
GPU 사이의 통신 비용도 함께 늘어날 수 있다.

따라서 다음 순서로 판단합니다.

  1. 모델이 한 GPU에 들어가는가?
  2. 여러 GPU가 데이터를 얼마나 자주 교환하는가?
  3. 통신이 같은 노드 안에서 끝나는가?
  4. 여러 노드가 필요하다면 네트워크와 RDMA가 요구사항을 만족하는가?

다음 Step에서는 GPU에 모델을 올리는 과정으로 내려갑니다.
모델이 실제로 Storage에서 GPU Memory까지 어떻게 이동하고,
Weight 크기를 어떤 공식으로 먼저 추정할 수 있는지 살펴보겠습니다.



🚀 Step 04. 모델은 GPU에 어떻게 올라가는가

🎯 이 Step의 질문

모델이 파일로 존재한다면, 왜 GPU Memory에 미리 올려두어야 할까?

LLM Serving을 시작할 때 가장 먼저 만나는 제약은 모델을 실행할 GPU Memory가 충분한지 여부입니다.

모델을 요청이 들어올 때마다 읽어 올 수는 없기 때문에,
일반적인 Serving System은 시작 과정에서 Weight를 준비하고 실행 중 재사용합니다.

💡 Model Loading 흐름

모델 Weight는 보통 다음 경로를 거쳐 GPU에 올라갑니다.

Model Storage
   ↓
CPU Memory
   ↓
GPU Memory
   ↓
Runtime 초기화·컴파일·Warmup
   ↓
요청 처리 가능

이 과정은 단순한 파일 복사가 아닙니다.

  • 원격 Storage에서 Weight 다운로드
  • Disk I/O
  • CPU Memory로 파일 읽기
  • CPU에서 GPU로 데이터 전송
  • GPU Memory 할당
  • Runtime 초기화와 Kernel 준비

이 중 어느 한 곳이 느리면 서버가 Ready 상태가 되는 시간이 길어집니다.

1. 왜 요청마다 모델을 로드하지 않을까?

모델 Weight가 CPU Memory나 Disk에만 있다면 요청이 올 때마다 GPU로 전송해야 합니다.
하지만 CPU Memory와 Disk는 GPU Memory보다 데이터 공급 속도가 느리기 때문에 실시간 Serving에 적합하지 않습니다.

이 장의 자료에는 다음과 같은 대역폭 범위 비교가 있습니다.

위치자료에서 제시한 예시 대역폭
SSD0.5–14 GB/s
CPU Memory50–200 GB/s
GPU Memory300 GB/s–3 TB/s

이 수치는 장치·세대·구성에 따라 달라지는 범위 예시입니다.
중요한 점은 정확한 숫자보다 실행 중 반복해서 읽는 Weight를 GPU Memory에 캐싱하는 이유입니다.

한 번 로드한 Weight를 GPU에 유지하면 각 요청은 모델을 다시 준비하지 않고 입력 처리와 Token 생성에 집중할 수 있습니다.

2. GPU Memory에 필요한 것은 Weight뿐일까?

아닙니다. 모델을 GPU에 올리는 순간 필요한 공간은 최소한 다음과 같습니다.

GPU Memory
├─ Model Weight
├─ KV Cache
├─ Activation
├─ Temporary Buffer
└─ Runtime Reserved Memory

이번 Step에서는 가장 먼저 계산할 수 있는 Model Weight 크기를 다룹니다.
KV Cache와 실행 중 메모리는 다음 Step에서 이어서 살펴봅니다.

3. Weight 크기 추정 공식

모델의 파라미터 수와 데이터 타입을 알면 Weight 크기를 대략 추정할 수 있습니다.

Weight Memory
≈ Parameter Count × Bytes per Parameter

정밀도별로 파라미터 하나가 차지하는 바이트 수는 다음처럼 생각할 수 있습니다.

PrecisionBit 수파라미터당 대략적인 크기
FP3232 bit4 bytes
FP16 / BF1616 bit2 bytes
INT8 / FP88 bit1 byte

정밀도를 낮추면 Weight Memory가 줄어들 수 있지만,
정확도·Kernel 지원·실제 처리 성능은 별도로 확인해야 합니다.

메모리가 절반이 되었다고 Serving 시간이 항상 절반이 되는 것은 아닙니다.

🧮 계산 예시: Llama-2-7B

예시와 같이 약 70억 개의 파라미터를 BF16으로 저장한다고 가정합니다.
BF16은 파라미터당 2 bytes를 사용합니다.

7,000,000,000 parameters × 2 bytes
≈ 14,000,000,000 bytes
≈ 14 GB

따라서 모델 Weight만 대략 14GB가 필요하다고 추정할 수 있습니다.

실제 파일 크기가 계산값과 정확히 같지 않은 이유는 다음과 같습니다.

  • GB와 GiB 단위 차이
  • 파일 Metadata와 Sharding
  • Weight Tying 여부
  • Quantization과 압축
  • Runtime이 추가로 사용하는 Buffer

그러므로 이 공식은 GPU를 고르기 위한 첫 번째 하한선 추정으로 사용하는 것이 좋습니다.

🧠 실행 전에 생각해보기

다음 모델의 Weight Memory를 계산해봅니다.

  1. 7B 모델을 FP16으로 저장한다.
  2. 같은 7B 모델을 INT8로 저장한다.
  3. 70B 모델을 BF16으로 저장한다.
모델PrecisionWeight Memory 대략값
7BFP16/BF1614 GB
7BINT8/FP87 GB
70BBF16140 GB

이 표는 Weight만 계산한 값입니다.

실제 Serving을 위해서는 KV Cache, Activation, Runtime Reserved Memory를 더할 공간이 필요합니다.

✅ Step 04의 핵심

Model Loading에서 먼저 기억할 것은 다음 세 가지입니다.

  1. Weight는 Storage에서 CPU Memory를 거쳐 GPU Memory로 이동합니다.
  2. 실행 중 반복해서 사용할 Weight는 GPU Memory에 유지하는 것이 일반적입니다.
  3. Parameter Count × Bytes per Parameter는 Weight 크기의 첫 추정치입니다.

다음 Step에서는 모델이 GPU에 들어갔는데도 OOM이 발생하는 이유를
살펴봅니다. 답은 요청마다 커지는 KV Cache와 실행 중 메모리에 있습니다.



🚀 Step 05. 모델이 올라간 뒤에도 GPU Memory가 부족한 이유

🎯 이 Step의 질문

Model Weight가 GPU에 들어갔는데, 왜 요청이 늘면 OOM이 발생할까?

모델을 GPU에 올리는 것과 여러 요청을 안정적으로 처리하는 것은 다른 문제입니다.

실행 중에는 각 요청의 Context와 생성 상태를 저장하기 위한 KV Cache가 계속 필요하기 때문입니다.

💡 KV Cache는 왜 필요한가?

Transformer가 다음 Token을 만들 때 이전 Token과 관련된 Attention 계산을 반복하면 같은 계산을 계속 수행해야 합니다.

처음 입력 처리
   ↓
Key·Value 계산
   ↓
KV Cache에 저장
   ↓
다음 Token 생성 때 재사용

이 방식은 계산을 줄여 Serving을 빠르게 만들 수 있지만, 저장 공간을 사용합니다.

요청 수와 Context Length가 커질수록 KV Cache도 함께 커집니다.

1. Token 하나에 필요한 KV Cache

기본적인 Multi-Head Attention(MHA)을 기준으로 Token 하나의 KV Cache를 다음처럼 근사할 수 있습니다.

KV Cache per Token
≈ 2 × Number of Layers
  × Number of KV Heads
  × Head Dimension
  × Bytes per Element

앞의 2는 Key와 Value를 함께 저장하기 때문에 붙습니다.

본문의 Llama-2-7B 예시는 MHA를 사용하므로 Attention Head 수와 KV Head 수가 같다고 볼 수 있습니다.
하지만 GQA나 MQA에서는 KV Head 수가 달라질 수 있습니다.
따라서 일반적인 공식에서는 Attention Head가 아니라 KV Head 수를 사용해야 합니다.

🧮 계산 예시: Llama-2-7B

다음 조건을 가정합니다.

  • Layer 수: 32
  • KV Head 수: 32
  • Head Dimension: 128
  • Element Size: 2 bytes, FP16/BF16
2 × 32 × 32 × 128 × 2
= 524,288 bytes
≈ 0.5 MiB per Token

Token 하나만 보면 작아 보이지만,
여러 요청과 긴 Context가 동시에 존재하면 크기가 빠르게 누적됩니다.

2. 전체 KV Cache 크기

전체 KV Cache는 다음처럼 생각할 수 있습니다.

Total KV Cache
≈ KV Cache per Token
  × Maximum Batch Size
  × Sequence Length

앞의 예시에서 Sequence Length 4,096과 Batch Size 16을 사용하면:

0.5 MiB × 4,096 × 16
≈ 32 GiB

Model Weight가 약 14GB였더라도 KV Cache만 약 32GiB가 필요할 수 있습니다.

여기에 Activation과 Runtime Buffer까지 더해지므로,
Weight만 GPU에 들어간다고 해서 충분하지 않습니다.

3. 메모리 예산으로 생각하기

Serving 중 GPU Memory 사용량을 단순화하면 다음과 같습니다.

전체 GPU Memory
├─ Model Weight: 서버 실행 동안 비교적 고정
├─ KV Cache: 요청 수와 Sequence Length에 따라 증가
├─ Activation: 현재 계산에 필요한 중간 결과
├─ Temporary Buffer: Kernel과 Runtime이 임시로 사용하는 공간
└─ 여유 공간: 피크 시 OOM을 피하기 위한 안전 영역

Idle 상태에서는 Weight가 대부분을 차지할 수 있습니다.

하지만 여러 요청을 처리하면 KV Cache와 중간 Buffer가 증가하여 Execution 상태의 Peak Memory가 더 커집니다.

4. Batch와 Context Length의 Trade-off

같은 GPU에서 Batch Size를 키우면 동시에 더 많은 요청을 처리할 수 있습니다.

하지만 KV Cache가 함께 증가하므로 다음 문제가 발생할 수있습니다.

  • 더 많은 요청을 처리할 수 있지만 GPU Memory가 부족해짐
  • 긴 Context를 허용할 수 있지만 동시 요청 수가 줄어듦
  • 이론상 계산 가능한 최대 Batch를 실제로는 Activation 때문에 사용할 수 없음

따라서 Serving 설정에서 다음과 같은 개념을 함께 확인합니다.

  • Maximum Number of Sequences
  • Maximum Model Length
  • Maximum Batched Tokens
  • GPU Memory Utilization

특정 프레임워크의 옵션 이름을 외우는 것보다,
동시 요청·Context·KV Cache 사이의 관계를 이해하는 것이 먼저입니다.

🧠 메모리 추정 연습

앞의 Llama-2-7B 예시에서 다음 상황을 비교해봅니다.

Batch SizeSequence LengthKV Cache 추정
14,096약 2 GiB
44,096약 8 GiB
164,096약 32 GiB
168,192약 64 GiB

이 표는 Weight와 Activation을 제외한 KV Cache만의 단순 추정입니다.
Batch와 Sequence Length 중 하나만 두 배가 되어도 KV Cache가 두 배가 되는 구조를 확인하는 것이 목적입니다.

⚠️ 이 공식의 한계

실제 KV Cache 크기는 다음 요인에 따라 달라질 수 있습니다.

  • MHA·GQA·MQA 등 Attention 구조
  • KV Cache의 Precision
  • Paged KV Cache와 Memory Fragmentation
  • Prefix Caching
  • Runtime이 예약하는 메모리
  • 실제 Batch와 요청별 Sequence Length 분포

따라서 “모델 크기의 두 배 GPU를 확보하라”는 이 장의 경험칙은 시작점일 뿐입니다.

모든 모델과 워크로드에 적용되는 법칙은 아닙니다.

✅ Step 05의 핵심

Model Weight가 GPU에 들어가는 것은 Serving의 시작 조건일 뿐입니다.

  1. KV Cache는 Token·Layer·KV Head·Head Dimension에 따라 커집니다.
  2. Batch Size와 Sequence Length가 늘면 KV Cache가 거의 비례해 증가합니다.
  3. 실제 GPU Memory 예산에는 Weight·KV Cache·Activation·Runtime 여유 공간이 모두 필요합니다.

다음 Step에서는 메모리 용량을 넘어, GPU가 실제로
연산을 기다리는지 데이터 이동을 기다리는지를 판단하는 도구를
살펴봅니다.

그 도구가 Arithmetic Intensity와 Roofline Model입니다.



🚀 Step 06. GPU는 연산 때문에 느린가, 메모리 때문에 느린가

🎯 이 Step의 질문

GPU의 TFLOPS가 충분히 높은데도 Serving이 느릴 수 있을까?

그럴 수 있습니다.

GPU가 계산할 수 있는 속도와 GPU에 데이터를 공급하는 속도는 서로 다른 제약입니다.

모델 Weight가 GPU Memory에 올라와 있어도,
실행 중에는 데이터가 Memory에서 연산 유닛까지 이동해야 합니다.

이번 Step에서는 이 둘 중 어느 쪽이 병목인지 생각하는 도구로
Arithmetic Intensity와 Roofline Model을 소개합니다.


💡 Data Movement: 실행 중에도 데이터는 이동한다

모델을 로드하는 과정과 모델을 실행하는 과정은 구분해야 합니다.

  • Model Loading: Storage와 CPU Memory에서 GPU Memory로 Weight를 이동
  • Model Execution: GPU Memory의 Weight와 중간 결과를 연산 유닛으로 이동

GPU 내부의 데이터 흐름을 단순화하면 다음과 같습니다.

GPU Memory(HBM/GDDR)
   ↓
L2·L1 Cache / Shared Memory
   ↓
Register
   ↓
Compute Unit

On-chip Memory인 SRAM은 작지만 빠르고,
GPU Memory인 HBM이나 GDDR은 상대적으로 큰 용량을 제공합니다.

실행 중 필요한 데이터가 GPU Memory에서 계속 읽혀야 한다면 Memory Bandwidth가 중요한 제한이 될 수 있습니다.

1. Arithmetic Intensity란?

Arithmetic Intensity는 이동한 데이터 양에 비해 얼마나 많은 연산을 수행하는지를 나타냅니다.

Arithmetic Intensity
= Number of FLOPs / Data Movement in Bytes

두 가지 경우를 비교해봅니다.

형태의미예상 병목
낮은 Arithmetic Intensity데이터를 많이 이동하지만 연산은 적음Memory Bandwidth
높은 Arithmetic Intensity적은 데이터를 재사용하며 연산이 많음Compute

낮은 Arithmetic Intensity의 Workload에서는 Compute 성능이 남아 있어도 데이터가 늦게 도착해 연산 유닛이 기다릴 수 있습니다.

2. Roofline Model

Roofline Model은 하드웨어의 Compute 한계와 Memory Bandwidth 한계를 하나의 그래프로 함께 보는 단순화된 모델입니다.


출처 - https://docs.nersc.gov/tools/performance/roofline/

  • x축: Arithmetic Intensity, FLOPs per Byte
  • y축: Attainable Performance
  • 기울어진 구간: Memory Bandwidth가 제한하는 영역
  • 수평 구간: Compute가 제한하는 영역
  • 두 구간이 만나는 지점: Crossover Point

Arithmetic Intensity가 Crossover Point보다 낮으면 데이터를 더 빨리 공급하는 것이 우선일 수 있습니다.

반대로 충분히 높으면 Compute 성능을 더 사용하는 방향이 중요해집니다.

3. L40S 계산 예시

이 장에서는 L40S의 FP16 Tensor Core 성능과 Memory Bandwidth를 이용해
이론적인 Crossover Point를 계산합니다.

362 TeraFLOPS / 864 GB/s
≈ 419 FLOPs/Byte

이 계산은 실제 애플리케이션 성능이 아니라 다음 조건을 둔 이상적인
근사입니다.

  • Peak FP16 Compute를 모두 사용할 수 있음
  • Memory Bandwidth를 이론적으로 모두 사용할 수 있음
  • Kernel Launch, Cache, 통신, Runtime Overhead를 제외함

따라서 419 FLOPs/Byte라는 숫자를 모든 Workload의 절대 기준으로 사용하면 안 됩니다.

여기서는 Roofline을 읽는 방법을 익히는 것이 목적입니다.

4. Matrix Multiplication의 Arithmetic Intensity

LLM의 Transformer Block에서는 Matrix Multiplication이 큰 비중을 차지합니다.

다음 형태를 생각해봅니다.

Input[M, K] × Weight[K, N] = Output[M, N]

단순화하면 연산 횟수와 데이터 이동량은 다음과 같습니다.

Operations
≈ 2 × M × N × K

Data Movement
≈ Bytes per Element × (M × K + K × N + M × N)

FP16처럼 Element 하나를 2 bytes로 저장한다고 가정하면:

Arithmetic Intensity
≈ M × N × K / (M × K + K × N + M × N)

분자와 분모에서 2가 서로 약분된 결과입니다.

🧮 행렬 크기에 따른 변화

M=N=K라고 단순화하면 이 장의 예시는 다음과 같습니다.

행렬 크기Arithmetic IntensityL40S 예시 기준 해석
64약 21 FLOPs/ByteMemory Bandwidth 영역
512약 170 FLOPs/ByteMemory Bandwidth 영역
4,096약 1,365 FLOPs/ByteCompute 영역

행렬이 커질수록 같은 데이터를 더 많이 재사용할 수 있어
Arithmetic Intensity가 커집니다.

🧠 계산 연습

다음 질문에 답해봅니다.

  1. 행렬 크기가 작을 때 GPU Compute가 남아 있을 수 있는 이유는 무엇인가?
  2. 행렬 크기가 커지면 왜 Compute-bound에 가까워질 수 있는가?
  3. 실제 Kernel이 이론식보다 낮은 성능을 낼 수 있는 이유는 무엇인가?

예상 답변은 다음과 같습니다.

  • 작은 행렬에서는 데이터를 이동하는 비용에 비해 연산량이 적습니다.
  • 큰 행렬에서는 이미 읽은 데이터를 여러 번 재사용할 수 있습니다.
  • Cache 효율, Kernel 구현, Synchronization, 실제 메모리 접근 패턴이 영향을 줍니다.

✅ Step 06의 핵심

GPU 성능을 볼 때는 “TFLOPS가 얼마인가?”에서 멈추지 말고
다음 질문으로 이어가야 합니다.

이 Workload는 데이터를 기다리는가, 아니면 계산을 기다리는가?

Arithmetic Intensity는 그 질문을 정량적으로 생각하게 해주고,
Roofline Model은 하드웨어의 Compute와 Memory 한계를 한 화면에서
비교하게 해줍니다.

다음 Step에서는 이 도구를 실제 LLM Serving의 두 단계,
Prefill과 Decode에 적용합니다.



🚀 Step 07. Prefill과 Decode의 병목은 왜 다른가

🎯 이 Step의 질문

같은 모델을 실행하는데, 왜 입력을 처리하는 단계와 답변을 생성하는 단계의 병목이 다를까?

LLM Serving은 크게 두 단계로 나눠 생각할 수 있습니다.

  • Prefill: 입력 Prompt 전체를 먼저 처리하는 단계
  • Decode: 이전 결과를 이용해 출력 Token을 하나씩 생성하는 단계

두 단계는 같은 Transformer Layer를 지나지만 한 번에 처리하는 Token의 수와 Tensor Shape가 다릅니다.

이 차이가 Arithmetic Intensity와 GPU 활용 패턴을 바꿉니다.


1. 입력 Tensor Shape

LLM의 입력 Tensor를 단순화하면 다음과 같습니다.

[Batch Size, Sequence Length, Hidden Dimension]
  • Batch Size: 동시에 처리하는 요청 수
  • Sequence Length: Prompt에 포함된 Token 수
  • Hidden Dimension: Token 하나를 표현하는 내부 벡터 크기

Batch Size가 1이면 입력을 다음과 같이 2차원 Matrix로 단순화할 수 있습니다.

[Sequence Length, Hidden Dimension]

이때 Sequence Length가 Matrix의 행 수와 비슷한 역할을 하게 됩니다.

2. Prefill: 입력 Token을 한꺼번에 처리

Prefill은 사용자가 보낸 Prompt를 모델에 처음 통과시키는 단계입니다.

이 단계에서 모델은:
1. 입력 Token 전체에 대한 Attention과 Layer 계산을 수행합니다.
2. 이후 Decode에 사용할 첫 번째 KV Cache를 생성합니다.

Prompt가 길면 한 번에 처리할 Token 수가 많아집니다.
따라서 Matrix의 행 수에 해당하는 Sequence Length가 커지고,
앞 Step의 단순화된 모델에서는 Arithmetic Intensity도 높아질 수 있습니다.

결과적으로 긴 Prompt의 Prefill은 Compute-bound에 가까워질 가능성이 있습니다.
하지만 모든 Prefill이 항상 Compute-bound라는 뜻은 아닙니다.

Batch, Kernel, Attention 구현, Memory 재사용에 따라 달라집니다.

3. Decode: Token을 하나씩 생성

Decode는 이미 계산한 KV Cache를 이용해 다음 Token을 반복적으로 생성하는 단계입니다.

단순화된 Batch Size 1 모델에서는 한 번에 새로 처리하는 Token 수가
1이므로:

s_prefill = Sequence Length
s_decode = 1

Hidden Dimension은 같지만 Decode의 행 수가 매우 작아집니다.

이 때문에 한 번 읽은 Weight를 큰 Matrix 연산으로 재사용하기 어렵고,
Weight와 KV Cache를 읽는 Memory Bandwidth의 영향이 커질 수 있습니다.

이 장에서는 이러한 단순화 아래 Decode가 낮은 Arithmetic Intensity를 보이며
Memory Bandwidth-bound에 가깝다고 설명합니다.

4. 산술 강도 비교

앞 Step의 Matrix Multiplication 공식을 LLM의 간단한 형태에 적용합니다.

M = s
N = K = h

Arithmetic Intensity
≈ s × h × h / (s × h + s × h + h × h)

여기서 s는 Sequence Length, h는 Hidden Dimension입니다.

앞서 살펴본 L40S 이론 예시처럼 h=4,096을 사용하면 다음과 같이 비교할 수 있습니다.

Sequence Length sPrefill Arithmetic IntensityDecode Arithmetic Intensity단순화한 해석
64약 62.06약 1.0둘 다 Memory Bandwidth 영향이 큼
512약 409.60약 1.0Prefill은 경계에 가까워짐
4,096약 1,365.33약 1.0Prefill은 Compute 쪽, Decode는 Memory 쪽

이 표의 Decode 값은 Batch Size 1과 s_decode=1을 고정한 결과입니다.
실제 Serving에서는 Continuous Batching과 동시 요청 수가 Shape를 바꾸므로
Decode가 모든 상황에서 항상 같은 병목이라는 의미는 아닙니다.

5. 사용자 경험 지표와 연결하기

Prefill과 Decode를 앞에서 배운 지표와 연결하면 다음과 같이 생각할 수
있습니다.

증상우선 확인할 구간관련 지표
첫 Token이 늦게 나옴Queue와 PrefillTTFT
첫 Token 후 생성 간격이 김DecodeInter-Token Latency
전체 응답이 늦게 끝남Decode와 응답 전달E2E Latency
긴 Prompt에서만 느림Prefill과 Context 처리TTFT, Prefill Time
동시 요청이 늘 때 악화Batch·KV Cache·MemoryTTFT, Throughput, GPU Memory

이 표는 원인을 확정하는 진단표가 아니라, 측정 순서를 정하는 가설입니다.
TTFT가 길다고 해서 항상 Prefill만의 문제라고 단정할 수는 없습니다.
Queue와 Model Loading도 TTFT에 포함될 수 있기 때문입니다.


🧠 적용 연습

다음 상황에서 어느 단계의 가설을 먼저 세울지 생각해봅니다.

  1. 짧은 Prompt는 빠르지만 긴 문서 요약 요청에서 첫 응답이 늦다.
  2. 첫 Token은 빨리 나오지만 긴 답변의 완료 시간이 길다.
  3. 동시 요청 수가 증가할 때 첫 응답과 전체 응답이 함께 느려진다.
상황첫 번째 가설
긴 Prompt에서 TTFT 증가Prefill과 입력 처리량
긴 출력에서 E2E 증가Decode와 출력 Token 생성
동시 요청 증가로 모두 악화Queue, Batch, KV Cache, Memory

실제 환경에서는 이 가설을 TTFT, Inter-Token Latency, E2E, GPU Memory,
Queue Length 등의 측정으로 확인해야 합니다.

✅ Step 07의 핵심

Prefill과 Decode는 같은 모델의 실행 단계지만 입력 Shape가 다릅니다.

  1. Prefill은 여러 Prompt Token을 함께 처리하므로 Sequence Length가 커질 수 있습니다.
  2. Decode는 새 Token을 하나씩 처리하므로 Batch Size 1에서는 행렬의 한 축이 작습니다.
  3. 따라서 Prefill은 조건에 따라 Compute-bound가 될 수 있고, Decode는 Memory Bandwidth의 영향을 크게 받을 수 있습니다.
  4. Batch와 Kernel 구현에 따라 실제 병목은 달라지므로 측정 없이 단정하면 안 됩니다.

다음 Step에서는 이런 하드웨어 제약을 다른 Accelerator와 Memory Wall 관점으로 넓혀 보고,
마지막에 운영 사례를 선택적으로 정리합니다.



🚀 Step 08. GPU 밖의 선택지와 Memory Wall

🎯 이 Step의 질문

NVIDIA GPU 외의 Accelerator가 있다면, 무엇을 기준으로 비교해야 할까?

앞의 Step에서는 GPU의 Memory, Compute, Interconnect가 LLM Serving의 병목에 어떻게 연결되는지 살펴봤습니다.
하지만 LLM 추론을 위한 하드웨어는 GPU 하나로 끝나지 않습니다.

다만 “어느 칩이 가장 좋은가?”라는 순위표를 만드는 것이 이번 Step의 목표는 아닙니다.

워크로드와 소프트웨어 환경에 따라 선택 기준이 달라지기 때문입니다.

1. 주요 Accelerator 분류

이 장에서는 다음과 같은 Accelerator를 소개합니다.

분류예시먼저 확인할 점
범용 GPU 대안AMD MI300X, Intel Gaudi2모델·Kernel·소프트웨어 호환성
클라우드 전용 AcceleratorGoogle TPU, Amazon Inferentia특정 클라우드와 SDK 의존성
지역·시장별 대안Huawei Ascend NPU공급망과 지역 제약
특화된 추론 칩Groq, Cerebras, SambaNova 등특정 지연시간·모델 구조에 대한 적합성

이 표는 이 장에서 제시한 분류를 학습용으로 정리한 것입니다.

제품의 현재 성능이나 시장 점유율을 비교하는 최신 표가 아닙니다.

2. Accelerator를 비교하는 다섯 가지 축

새로운 칩을 볼 때는 GPU 이름 대신 다음 질문을 반복합니다.

질문확인할 내용
모델이 들어가는가?Memory Capacity와 모델 분할 필요성
데이터를 빨리 공급하는가?Memory Bandwidth와 On-chip Memory
연산을 충분히 활용하는가?Precision, Tensor 연산, Kernel 지원
여러 칩이 협력하는가?Interconnect와 통신 라이브러리
실제로 운영할 수 있는가?SDK, Framework, 인력, 공급, 전력, 비용

특히 NVIDIA GPU에서 다른 Accelerator로 바꾸는 일은 하드웨어만 교체하는 작업이 아닐 수 있습니다.

  • CUDA Kernel과 연산 라이브러리
  • Model Runtime과 Serving Framework
  • Quantization·Precision 지원
  • Monitoring과 장애 대응 방식
  • 팀의 운영 경험과 디버깅 도구

까지 함께 바뀔 수 있습니다.

3. Memory Wall이란?

여기서 주목할 문제는 Memory Wall입니다.

시간이 지나면서 GPU와 Accelerator의 Peak FLOPS는 빠르게 증가했지만,

데이터를 이동시키는 Memory Bandwidth와 Interconnect Bandwidth는 같은 속도로 증가하지 않을 수 있습니다.

연산 성능 증가 속도
        >
데이터 이동 성능 증가 속도
        ↓
계산 유닛이 데이터를 기다리는 시간 증가
        ↓
Memory Wall

이 관점은 Step 06의 Arithmetic Intensity와 연결됩니다.

계산량이 많아도 데이터 이동이 따라오지 못하면 GPU의 Peak Compute를 실제로 활용하지 못할 수 있습니다.

4. Memory Wall을 줄이려는 두 가지 방향

방향 A. 연산 유닛 가까이에 데이터를 두기

On-chip SRAM은 용량이 작고 비싸지만 연산 유닛 가까이에 위치해 지연시간을 줄일 수 있습니다.

이 방향은 다음과 같은 장점을 기대할 수 있습니다.

  • 데이터 이동 거리와 지연시간 감소
  • 예측 가능한 낮은 지연시간
  • 특정 추론 Workload에서 높은 효율

반면 모델 크기가 커질수록 여러 칩으로 분할해야 할 수 있고,
칩 비용과 소프트웨어 제약이 커질 수 있습니다.

방향 B. 여러 GPU를 하나의 시스템처럼 결합하기

다른 방향은 GPU와 CPU, GPU와 GPU를 고대역폭·저지연 Interconnect로 긴밀하게 결합하는 것입니다.

이 장에서는 Grace CPU, Blackwell GPU, GB200 NVL72와 같은 Rack-scale 구성을 사례로 소개합니다.

이런 구조에서는 많은 GPU를 하나의 통신 도메인으로 묶어 대형 모델과 MoE 모델을 처리하려고 합니다.

하지만 이 역시 단순히 GPU 개수를 늘리는 문제는 아닙니다.

  • 모델을 어떤 방식으로 분할할 것인가
  • Prefill과 Decode를 분리할 것인가
  • Expert를 어느 칩에 배치할 것인가
  • 통신량과 장애 범위를 어떻게 관리할 것인가

를 함께 설계해야 합니다.

⚠️ 이 Step에 등장하는 Accelerator와 Rack-scale 구성은 이 장에서 인용한 학습용 사례입니다.
최신 제품 사양·가격·시장 점유율·성능 순위로 사용하려면 별도의 공식 자료 확인이 필요합니다.

🧠 선택 연습

다음 상황에서 어떤 축을 가장 먼저 확인할지 생각해봅니다.

  1. 모델이 한 칩의 Memory에 들어가지 않는다.
  2. 작은 Batch의 Decode에서 데이터 이동이 병목이다.
  3. 팀은 특정 Accelerator SDK 경험이 없고 CUDA 기반 코드가 많다.
  4. 매우 낮고 예측 가능한 지연시간이 최우선이다.
상황먼저 확인할 축
모델이 들어가지 않음Memory Capacity와 Sharding
Decode가 느림Memory Bandwidth와 On-chip Memory
Migration 부담이 큼Software Ecosystem과 Kernel 호환성
초저지연이 최우선SRAM 구조와 고정된 실행 방식

이 연습의 목적은 특정 칩을 고르는 것이 아니라,
워크로드의 병목과 하드웨어의 강점을 연결하는 습관을 만드는 것입니다.

✅ Step 08의 핵심

LLM Serving 하드웨어를 선택할 때는 다음 순서로 생각합니다.

  1. 모델과 KV Cache가 들어갈 Memory가 있는가?
  2. Workload가 Compute-bound인가 Memory-bound인가?
  3. 필요한 Multi-chip 통신을 감당할 Interconnect가 있는가?
  4. Framework와 Kernel을 실제로 운영할 수 있는가?
  5. 공급·전력·비용·장애 대응까지 감당할 수 있는가?

결국 좋은 Accelerator는 절대적으로 정해져 있지 않고,
자신의 Workload와 운영 조건에 맞는 Accelerator입니다.



✅ CH05. 마무리

이번 장에서는 LLM Serving을 단순히 “모델이 Token을 생성하는 과정”으로 보지 않고,
하드웨어와 요청 흐름이 결합된 시스템으로 살펴봤습니다.

1. 왜 Serving 최적화가 필요한가

Serving의 목표는 무조건 가장 빠른 응답이 아닙니다.

  • 사용자가 첫 응답을 언제 받는가
  • 전체 답변이 언제 끝나는가
  • 같은 GPU로 몇 개의 요청을 처리하는가
  • Peak Traffic에서도 서비스를 유지하는가
  • 필요한 품질을 감당 가능한 비용으로 제공하는가

Customer Experience, Cost Efficiency, Scalability·Peak Load·Feasibility를 함께 봐야 합니다.

2. GPU를 어떻게 읽는가

GPU는 TFLOPS 하나로 판단할 수 없습니다.

Compute
+ Memory Capacity
+ Memory Bandwidth
+ Interconnect
+ Power

모델이 GPU에 들어가는지,
실행 중 Weight와 KV Cache를 공급할 수 있는지,
여러 GPU가 통신을 감당할 수 있는지를 함께 확인해야 합니다.

3. 모델은 어떻게 메모리를 사용하는가

Model Loading에서는 Weight가 Storage에서 CPU Memory를 거쳐 GPU Memory로 이동합니다.

Weight 크기는 Parameter Count와 Precision으로 먼저 추정할 수 있지만,
실제 Serving에서는 KV Cache·Activation·Runtime Buffer가 추가로 필요합니다.

특히 KV Cache는 Batch Size와 Sequence Length가 커질수록 증가하므로,
모델이 GPU에 들어간다는 사실만으로 동시 요청 처리 가능성을 판단할 수 없습니다.

4. 실행 병목은 어떻게 구분하는가

Arithmetic Intensity와 Roofline Model을 사용하면 GPU Workload가
Compute-bound인지 Memory Bandwidth-bound인지 생각할 수 있습니다.

Prefill과 Decode는 같은 모델을 실행하지만 처리하는 Tensor Shape가 다르므로 병목도 달라질 수 있습니다.

  • Prefill: 긴 Prompt를 한꺼번에 처리하며 Compute-bound가 될 수 있음
  • Decode: 한 번에 한 Token을 생성하며 Memory Bandwidth의 영향을 크게 받을 수 있음

이 결론은 Batch Size, Kernel, Attention 구조, Runtime 구현에 따라 달라질 수 있으므로 실제 측정 없이 절대적인 규칙으로 사용하면 안 됩니다.

🧭 CH05에서 얻어야 할 사고 순서

Serving 문제가 생겼을 때 다음 순서로 질문합니다.

사용자 증상
   ↓
TTFT인가, E2E인가, Throughput인가?
   ↓
Queue·Model Loading·Prefill·Decode 중 어디인가?
   ↓
Memory Capacity·Memory Bandwidth·Compute·Interconnect 중 무엇인가?
   ↓
설정·Kernel·Batch·Precision·Hardware 중 무엇을 바꿀 것인가?

이 흐름이 있으면 새로운 Framework나 Accelerator가 등장해도,
이름을 먼저 외우기보다 문제와 병목을 기준으로 이해할 수 있습니다.

⚠️ 이번 장에서 측정하지 않은 것

이번 CH05 정리는 다음을 직접 측정한 벤치마크가 아닙니다.

  • GPU별 실제 Serving 성능
  • 특정 모델의 실제 비용 절감률
  • Interconnect의 실측 대역폭
  • Prefill·Decode의 실제 Kernel 성능
  • Accelerator 간 성능 순위

앞서 인용한 수치와 사례는 개념을 설명하기 위한 예시로 구분했습니다.

실제 환경의 결론을 내리려면 동일한 모델·Precision·Batch·Context·Runtime 조건에서 별도의 측정이 필요합니다.

🔗 다음 장으로

CH05에서 만든 기초 위에 다음 장에서는 LLM Serving을 더 효율적으로 만드는 구체적인 기법을 다루게 됩니다.

  • Batching과 Scheduling
  • KV Cache 관리
  • Attention과 Kernel 최적화
  • Quantization
  • Prefill·Decode 분리
  • 모델과 하드웨어에 맞는 Serving 구성

이제부터 중요한 것은 새로운 기법을 많이 아는 것이 아니라,
어떤 병목을 해결하기 위해 그 기법을 선택하는가를 설명하는 것입니다.

profile
안녕하세요! DevOps 엔지니어 이재찬입니다. 블로그에 대한 피드백은 언제나 환영합니다! 기술, 개발, 운영에 관한 다양한 주제로 함께 나누며, 더 나은 협업과 효율적인 개발 환경을 만드는 과정에 대해 인사이트를 나누고 싶습니다. 함께 여행하는 기분으로, 즐겁게 읽어주시면 감사하겠습니다! 🚀

0개의 댓글