Skip to main content

LLM 게이트웨이 세 갈래를 AWS에서 측정하기 - vllm-router · Agent Router · llm-d

· 36 min read
Jinwoong Kim
Technologist and Cloud Consultant

해당 포스팅은 현재 재직 중인 회사와 관련이 없고, 개인 역량 개발을 위한 스터디 자료로 활용할 예정입니다.

측정 환경: AWS EC2 g6.12xlarge (NVIDIA L4 24GB × 4, NVLink 없음) · K3s v1.36.4 · vLLM 0.11.0 · Qwen3-0.6B-FP8 × 2 (각 GPU 1장) · vllm-router 0.1.15 · Envoy Gateway v1.9.1 · Agent Router (Envoy AI Gateway) v1.1.0 · GAIE v1.0.1

vLLM 앞에 둘 수 있는 세 구현체를 검토했다. 대상은 vLLM 앞단에 두는 별도 패키지 vllm-router, Envoy 기반 Agent Router(구 Envoy AI Gateway), llm-d였다. 다만 세 구현체를 모두 성능 측정에 넣지는 못했다. Agent Router는 Envoy Gateway와 InferencePool의 호환성 문제로 라우팅 성능을 측정하지 못했고, llm-d는 standalone Envoy 경로에 GAIE EPP를 연결해 approximate 프리픽스 라우팅만 측정했다. 설치와 연동 과정은 8절에 따로 기록했다.

성능 측정에는 K8s Service 대조군을 포함해 다음 다섯 구성을 사용했다.

경로구성파드 선택 방식
K8s Servicekube-proxy연결 단위 분배
vllm-routerround_robin두 파드에 번갈아 분배
vllm-routercache_aware 기본 설정라우터가 추적한 프리픽스 기준
vllm-routercache_aware + 균형 임계값 4096/100프리픽스 우선 선택이 부하 균형 판단에 덮이지 않도록 임계값 조정
llm-d standalone Envoy 경로 + GAIE EPPprefix-cache-scorerEPP가 추정한 프리픽스 캐시 점수 기준

다섯 구성을 같은 GPU와 모델에 올리고 동일한 부하를 걸었다. 처리량 자체보다 "게이트웨이가 달라지면 어떤 차이를 보이는가"를 확인하려는 시험이었다. 그러나 다섯 구성의 처리량과 지연은 사실상 같았다. 이에 워크로드가 도달할 수 있는 상한을 별도로 측정한 뒤 실제 구성과의 차이를 계산했다.

이 워크로드에서 게이트웨이 계층이 활용할 수 있었던 성능 차이는 캐시 히트율 34.7포인트, 처리량 13.6%, p99 TTFT 56%였다. 성능을 측정한 다섯 구성은 이 차이를 실제 성능으로 바꾸지 못했다.

GPU 인식 경로를 AWS G 타입에서 따라가기 - 드라이버부터 K8s DRA까지

· 42 min read
Jinwoong Kim
Technologist and Cloud Consultant

해당 포스팅은 현재 재직 중인 회사와 관련이 없고, 개인 역량 개발을 위한 스터디 자료로 활용할 예정입니다.

로컬 PC에서 테스트한 내용은 gasida 님이 작성하신 설치 가이드를 참고했습니다.

비교 기준: 로컬 PC(RTX 4070 Ti SUPER, GeForce) 환경의 같은 절차

측정 환경: AWS EC2 g6.2xlarge (NVIDIA L4 24GB, compute capability 8.9) · 순정 Ubuntu 24.04.4 LTS AMI · NVIDIA Driver 595.84 / CUDA 13.2 · Container Toolkit 1.20.0 · K3s v1.36.4 · device-plugin v0.20.0 · DCGM Exporter 4.6.0 · NFD 0.18.3 · HAMi v2.10.0 · vLLM 0.28.0

GPU가 꽂힌 물리 PC에 Ubuntu를 깔고 드라이버부터 쿠버네티스 GPU 분할까지 올리는 방법을 바탕으로 AWS EC2에서 그대로 진행해 보고 로컬 PC 환경과 어떤 부분에 차이가 있는지 비교하고 기록했다.

Deep Learning AMI를 쓰지 않았다. 앞선 실습들은 드라이버가 미리 깔린 DL용 AMI를 썼는데 이번에는 드라이버 설치 과정 자체가 주요 내용이다. DKMS 빌드, .ko.zst 모듈, /dev/nvidia* 장치 노드가 어떻게 생기는지 보려면 순정 이미지에서 시작해야 한다. 그래서 Canonical 순정 Ubuntu 24.04 AMI로 진행했다.

결론부터 말하자면 계획한 항목이 Utilyze 하나만 빼고 전부 통과했고 로컬 PC와 갈린 지점이 몇 가지 확인되었다. kubeadm과 GPU Operator를 전제로 한 후반부(HAMi, DRA)는 K3s에서 수동 스택으로 돌리려면 손을 봐야 했고, 그 과정에서 나온 것들을 정리했다.

LLM 최적화 실전 프로젝트 - 단일 인스턴스 처리량 최대화

· 19 min read
Jinwoong Kim
Technologist and Cloud Consultant

해당 포스팅은 현재 재직 중인 회사와 관련이 없고, 개인 역량 개발을 위한 스터디 자료로 활용할 예정입니다.

원본 학습 자료: O'Reilly Hands-On LLM Serving and Optimization (Chi Wang, Peiheng Hu) 9장 · 실습 코드 orca3/llm-model-inference/ch09

측정 환경: AWS EC2 g6e.2xlarge (NVIDIA L40S 46GB, compute capability 8.9) · g6.12xlarge (L4 24GB x4, NVLink 없음, 도전과제) · vLLM 0.28.0 · Qwen3-14B / Qwen3-14B-AWQ

8장까지는 기법을 하나씩 떼어 봤다. 이 장은 그것들을 한 모델에 순서대로 얹어 보는 자리다. 목표는 단일 인스턴스의 토큰 처리량을 최대로 끌어올리는 것이고 순서는 하드웨어 확인 → 트래픽 설계 → 지표 정의 → 기준선 측정 → 양자화 → 추가 튜닝이다.

측정하면서 자료와 어긋난 지점이 두 곳 나왔다. 양자화는 자료가 예상한 것보다 ITL을 훨씬 크게 개선했고 반대로 자료가 권한 fine-tuned 설정은 성능을 떨어뜨렸다. 두 지점의 원인은 같았다.

마지막에 자료가 인용만 하고 직접 재지 않은 질문 하나를 따로 측정했다. GPU 두 장이 있을 때 TP로 쪼개는 것과 독립 인스턴스 두 대로 나누는 것 중 무엇이 나은가.

고급 LLM 최적화 - 추측 디코딩 · 병렬화 · PD 분리 · KV 캐시 계층

· 55 min read
Jinwoong Kim
Technologist and Cloud Consultant

해당 포스팅은 현재 재직 중인 회사와 관련이 없고, 개인 역량 개발을 위한 스터디 자료로 활용할 예정입니다.

원본 학습 자료: O'Reilly Hands-On LLM Serving and Optimization (Chi Wang, Peiheng Hu) 7-8장

측정 환경: AWS EC2 g6.xlarge (NVIDIA L4 24GB, compute capability 8.9) · g5.12xlarge (A10G 24GB x4, NVLink 없음) · g6.12xlarge (L4 24GB x4, NVLink 없음, 5절 재현) · Qwen2.5-7B-Instruct 타깃 + Qwen2.5-0.5B-Instruct 드래프트

양자화까지 적용하고 나면 단일 GPU에서 짜낼 수 있는 것은 대체로 다 짜낸 상태가 된다. 그다음에 남는 선택지가 이 글에서 다루는 네 가지다. 작은 모델로 토큰을 미리 찍어보는 추측 디코딩, 모델을 여러 GPU에 쪼개는 병렬화, 입력 처리와 출력 생성을 물리적으로 분리하는 PD 분리, 그리고 KV 캐시를 GPU 밖까지 계층으로 관리하는 방법이다. 마지막으로 이 기법들을 실제로 구현해 주는 서빙 프레임워크를 비교한다.

네 기법의 성격이 꽤 다르다. 추측 디코딩과 KV 캐싱은 GPU 한 장에서도 효과를 볼 수 있고 병렬화와 PD 분리는 애초에 GPU가 여러 장 있어야 성립한다. 측정한 것과 개념 정리에서 멈춘 것을 절마다 표시해 두었다.

한 가지만 미리 적어둔다. 추측 디코딩은 흔히 "지연을 2~3배 줄인다"고 소개되는데 이 숫자에는 동시성이 낮을 때라는 조건이 빠져 있다. GPU가 한가할 때 남는 연산으로 미리 토큰을 찍어보는 기법이라서 GPU가 이미 배치로 꽉 차 있으면 이득이 사라지고 오히려 손해가 될 수 있다.

양자화 3종 벤치마크 - BF16 · FP8 · GPTQ-Int4

· 18 min read
Jinwoong Kim
Technologist and Cloud Consultant

해당 포스팅은 현재 재직 중인 회사와 관련이 없고, 개인 역량 개발을 위한 스터디 자료로 활용할 예정입니다.

원본 실습: O'Reilly Hands-On LLM Serving and Optimization (Chi Wang, Peiheng Hu) ch06/quantization_3way_300.ipynb

검증 환경: AWS EC2 g6e.xlarge (NVIDIA L40S 48GB, compute capability 8.9) · vLLM 0.8.5.post1 · transformers 4.51.3 · CUDA 12.4 · Qwen2.5-7B-Instruct

양자화 설명은 보통 "가중치 정밀도를 낮추면 메모리가 줄고 속도가 빨라진다"에서 멈춘다. 틀린 말은 아닌데, 막상 서비스에 넣을지 결정하려고 하면 이 문장만으로는 아무것도 고를 수 없다. 얼마나 빨라지는지, 어떤 상황에서 빨라지는지, 그 대가로 무엇을 내주는지까지 알아야 판단이 선다.

그래서 Qwen2.5-7B 한 모델을 세 가지 정밀도로 준비해 같은 GPU에 번갈아 올리고, 동시성을 1에서 300까지 올려가며 직접 재봤다. 비교 대상은 BF16 원본, FP8-dynamic(W8A8), GPTQ-Int4(W4A16) 세 가지다.

결론부터 적으면, 모든 지표를 다 가져가는 변형은 없었다. 처리량은 GPTQ-Int4가 전 구간에서 1위였지만, 동시성이 높을 때의 지연과 원본 대비 출력 충실도는 둘 다 FP8이 가장 좋았다. 함정도 하나 있는데, 인스턴스 타입을 잘못 고르면 FP8이 에러 하나 없이 W8A16으로 격하돼서 비교 자체가 무의미해진다.