대규모 LLM 추론 심층 분석 — Harshul Jain(Audible) & Tanmay Sah(독립 AI 연구원)

AAI Engineer
컴퓨터/소프트웨어경제 뉴스AI/미래기술

스크립트

00:00:00그럼 다들 좋은 오후입니다. 제 이름은 하샬 진이고 옆에 분은 탄미샤입니다. 저희는
00:00:21LLM 추론에 관한 이 두 시간짜리 워크숍에 여러분을 환영하고자 합니다.
00:00:26이 워크숍의 목표는 제1원칙부터 이 도메인을 이해하고,
00:00:33더 깊이 파고들어 업계 전반에서 어떤 일이 일어나고 있는지
00:00:39파악하는 것입니다. 저희에 대해 간단히 소개해 드리자면, 저는 오디블의 시니어 소프트웨어 엔지니어로
00:00:47지난 5년 동안 ML/AI 데이터 플랫폼을 구축해 왔으며,
00:00:53부수적으로 LLM 추론에 관한 오픈소스 핸드북을 집필해 왔습니다. 그리고
00:00:59탄마이는 시안스 뱅크 코퍼레이션의 시니어 양적 모델러입니다. 그는
00:01:06최근 박사 학위를 마치고 에이전트 검증기와 세계 모델 분야에서 활발히 연구를
00:01:12수행해 왔습니다. 자, 가볍게 거수 부탁드립니다. LLM 추론이 완전히 처음이신 분은 누구인가요?
00:01:24네, 좋습니다. 그럼 이 모델들을 프로덕션에 배포해 보신 분은요? 튜닝도 해보고,
00:01:33프로덕션 트래픽을 서빙해 보신 분들이요. 네, 좋습니다. 그렇다면 이
00:01:42워크숍은 초급 및 중급 수준을 대상으로 합니다. 그리고 모든
00:01:48슬라이드와 실습 코드는 저장소에 있으며 곧 공유해 드리겠습니다. 워크숍의 간략한
00:01:56아젠다는 다음과 같습니다. 먼저 문제 정의부터 시작하겠습니다. LLM 추론과 관련된
00:02:01몇 가지 고충점을 이해해 보려 합니다. 그런 다음 그러한 고충점의 원인을 파악하고
00:02:08그로부터 기초를 다질 것입니다. 이어서 우리가 수행하는 두 가지 종류의
00:02:14최적화, 즉 모델 최적화와 서빙
00:02:19최적화에 대해 깊이 알아봅니다. 그런 다음 프로덕션에 LLM 추론 솔루션을 배포하기 위해
00:02:25사용할 수 있는 다양한 서빙 엔진에 대해 배우고, 몇 가지 벤치마크와
00:02:32어떤 엔진을 사용해야 할지 보여주는 의사결정 차트를 소개하겠습니다.
00:02:39좋습니다. 고충점을 이해하려면 먼저 LLM 추론이란 무엇인지 알아야 합니다. 그래서
00:02:47아마 우리 중 많은 분들이 이미 알고 계실 것입니다. 하지만 비디오, 오디오 생성, 텍스트 분석, 의료 보고서 분석 등
00:02:55AI에게 시키는 모든 작업,
00:03:02세금 고지서 분석 등이 모두 LLM 추론입니다. 그리고 이 시장은 현재 약 230억 달러 규모입니다.
00:03:12세미애널리시스(SemiAnalysis)는 최근 구글 검색 쿼리를 LLM으로 모델링하려면 360억 달러 규모의 자금 유출이 필요하다고 밝혔습니다.
00:03:25그리고 검색 사업을 수익성 있게 유지하려면 쿼리당 비용이 0.5센트 미만이어야 합니다.
00:03:33반면 비즈니스 인사이더는 AI가 제대로 작동해야 하며 모든 사람이 토큰 사용량을 감사하고 예산을 책정하기 시작해야 한다고 언급했습니다.
00:03:43이 모든 일이 왜 일어날까요? 하드웨어가 한정되어 있고, 연산 비용이 비싸며, 추론 비용이 비싸기 때문입니다.
00:03:50그리고 AI 사용이 점점 늘어남에 따라 이 추론 비용은 갈수록 치솟고 있습니다.
00:04:03이 통계는 오픈AI의 오래된 통계이지만 여전히 유효합니다.
00:04:11GPT-3의 훈련 비용을 살펴보면 대략 460만 달러 정도였습니다. 일회성 비용이었죠.
00:04:19하지만 추론 비용을 보면, 이는 유입되는 모든 사용자, 유입되는 모든 토큰, AI에서 시작되는 모든 세션에 따라 규모가 커지는 운영 비용이기 때문에 반복적인 비용입니다.
00:04:36이에 대응하는 방법은 기본적으로 두 가지뿐인데, 한 가지 방법은 토큰 사용량을 줄이는 것입니다.
00:04:47대안은 고객과 자신을 위해 추론 서비스 제공업체로서 추론 솔루션을 최적화하려고 노력하는 것입니다.
00:04:58그래서 우리는 매 순간 수많은 새로운 솔루션이 나오는 것을 목격해 왔습니다.
00:05:06따라서 앞으로 출시될 그 어떤 기술이든 이해하고 평가하는 데 도움이 될 기반을 다져보자는 아이디어입니다.
00:05:18그럼 시작하기 위해, 추론과 관련된 다양한 고충점이 무엇인지 간단한 데모를 진행하겠습니다.
00:05:28이것은 저장소입니다.
00:05:31클론할 수도 있고 GitHub에서 열어볼 수도 있습니다.
00:05:36이름은 'LLM Inference at Scale'입니다.
00:05:39배경을 조금 말씀드리자면, 4개월 전에 저는 LLM 추론에 대해 아무것도 몰랐을 때 공부를 시작했습니다.
00:05:46많은 리소스들이 흩어져 있다는 것을 알게 되었죠.
00:05:49그래서 사람들에게 도움이 되도록 그 모든 것을 한곳에 모으기 시작했습니다.
00:05:55네, 그럼 실제로 이 슬라이드 쇼 모드에서 나와서 확장 모드로 들어가 보겠습니다.
00:06:11네, 이 저장소에서 README 파일을 보면 슬라이드 링크가 있습니다.
00:06:27이 폴더에는 PPTX와 벤치마크 보고서가 들어 있습니다.
00:06:34언제든지 다운로드할 수 있으며, 데모를 위해 몇 개의 주피터 노트북을 준비했습니다.
00:06:43Google Colab의 대안인 Molab과 협력하여 무료 RTX 6000 GPU를 제공하고 있습니다.
00:06:54따라서 100GB RAM GPU이며, 쉽게 실험해 볼 수 있도록 이러한 노트북을 이미 설정해 두었고 모든 자산과 설정이 미리 준비되어 있습니다.
00:07:09그럼 간단한 데모 A부터 시작하겠습니다.
00:07:16아마도, 잠시만요.
00:07:31네, 추론을 할 때는 특정 모델로 추론을 수행해야 하잖아요?
00:07:40그래서 워크숍을 위해 간단한 Mistral 7B 모델을 사용하고 있습니다.
00:07:45크기가 약 15GB인 작은 모델입니다.
00:07:49따라서 이를 GPU에 로드할 것입니다.
00:07:53그리고 몇 가지 GPU 통계도 살펴볼 것입니다.
00:07:58보시다시피 우리는 6000 블랙웰(Blackwell)에서 작업하고 있습니다.
00:08:01컨퍼런스 와이파이를 신뢰하지 않기 때문에 제가 셀을 실행하지 않는다고 생각하실 수도 있습니다.
00:08:08그래서 이전에 실행했던 결과를 바탕으로 살펴보겠습니다.
00:08:18네, 102GB짜리 GPU가 있습니다.
00:08:22자, LLM 추론을 수행할 때 가장 먼저 떠오르는 것은 메모리 소비량이 어떻게 되는가입니다.
00:08:31이 모델을 로드하고 보니 대략 15GB를 차지합니다.
00:08:37따라서 대략 87.5GB가 남습니다.
00:08:40이제 여기서 추론을 수행해 보면, 입력하는 데이터의 수가 많을수록 더 많은 메모리가 필요하다는 것을 알 수 있습니다.
00:08:52서서히 증가하지만 여전히 증가하고 있습니다.
00:08:56컨텍스트 길이가 4,000, 16,000, 또는 32,000 토큰 정도라고 상상해 보세요.
00:09:03그럼 이 메모리가 정말 크게 늘어나서 실제로 메모리 부족(OOM) 문제가 발생할 수 있습니다.
00:09:12따라서 이것이 첫 번째 문제, 즉 토큰 증가에 따라 메모리가 증가하는 문제입니다.
00:09:18간단한 시각화 형태로 보면 다음과 같습니다.
00:09:24두 번째로 보게 될 문제는 첫 토큰 생성 시간(TTFT)이 매우 매우 느리다는 점입니다.
00:09:32TTFT라는 지표로 측정합니다.
00:09:35줄임말입니다.
00:09:37입력 크기에 따라 TTFT를 측정해 보면 컨텍스트가 길어질수록 이 TTFT가 느려지는 것을 볼 수 있습니다.
00:09:52자, 이제 두 가지 문제가 있습니다.
00:09:54토큰 크기에 따라 메모리가 증가합니다.
00:09:56토큰 크기에 따라 TTFT가 증가합니다.
00:09:59죄송합니다, 토큰 크기가 아니라 컨텍스트 크기입니다.
00:10:07그리고 세 번째는 처리량(Throughput)입니다.
00:10:09처리량은 초당 몇 개의 토큰을 서빙할 수 있는가입니다.
00:10:13그리고 초당 몇 명의 사용자를 지원할 수 있는가입니다.
00:10:16로컬 시스템에 아주 아주 순수한(vanilla) 구현을 적용하면 매우 순차적일 것입니다.
00:10:24따라서 요청 5개를 보내면 그 5개의 요청이 병렬이 아니라 순차적으로 처리됩니다.
00:10:31그래서 사용자 수가 많아지면 요청을 처리하는 데 더 오랜 시간이 걸리게 됩니다.
00:10:40이러한 세 가지 문제가 있습니다.
00:10:43네 번째 문제도 있습니다.
00:10:44여기서는 설명하지 않았습니다.
00:10:45아마 진행하면서 그 직관을 쌓아가게 될 것입니다.
00:10:48하지만 기억해야 할 것은 이 세 가지 문제, 즉 메모리, TTFT, 그리고 처리량입니다.
00:10:55좋습니다.
00:10:56다시 슬라이드로 돌아가겠습니다.
00:11:02알겠습니다.
00:11:03완벽합니다.
00:11:04이 화면이어야 합니다.
00:11:17보이나요?
00:11:18네.
00:11:19보입니다.
00:11:20보입니다.
00:11:21네.
00:11:22보입니다.
00:11:23보입니다.
00:11:24보입니다.
00:11:25네.
00:11:26보입니다.
00:11:27보입니다.
00:11:28네.
00:11:29보입니다.
00:11:30네.
00:11:31보입니다.
00:11:32네.
00:11:33보입니다.
00:11:34네.
00:11:35보입니다.
00:11:36보입니다.
00:11:37네.
00:11:38보입니다.
00:11:39네.
00:11:40보입니다.
00:11:41네.
00:11:42보입니다.
00:11:43네.
00:11:44보입니다.
00:11:45네.
00:11:46네.
00:11:47따라서 해당 저장소 내에서 워크숍 폴더를 보면 README가 있고, 그 README에
00:11:55모든 링크, 슬라이드, 데모가 있습니다.
00:12:01잘 되나요?
00:12:06알겠습니다.
00:12:07완벽합니다.
00:12:09좋습니다.
00:12:10완벽합니다.
00:12:16자,
00:12:17이제 기초부터 차근차근 살펴보겠습니다.
00:12:19이러한 고충점의 이면에 있는 원인이 무엇인지 이해해 봅시다.
00:12:25그러기 위해서 이 추론 파이프라인을 살펴봐야 합니다.
00:12:32입력 텍스트가 있다고 가정해 봅시다.
00:12:35이 텍스트는 임의의 수의 단어를 포함할 수 있습니다.
00:12:38우리는 그 단어들을 토큰으로 변환합니다.
00:12:41따라서 간단히 단어 하나가 토큰 하나와 같다고 가정할 수 있죠.
00:12:46그런 다음 이를 임베딩으로 변환하고 트랜스포머에 전달합니다.
00:12:53트랜스포머 레이어가 32개 있지만, 이는 미스트랄 7B에만 해당하는 특성입니다.
00:12:58모델마다 레이어의 종류와 개수가 다르죠.
00:13:01그리고 새로운 토큰을 생성하게 됩니다.
00:13:04그 토큰은 기본적으로 다시 입력으로 들어가고,
00:13:06또 다른 토큰을 생성하는 과정이 계속 반복됩니다.
00:13:09이 전체 파이프라인에서 연산의 약 95%가 이 트랜스포머 레이어에 의해 소모된다는 것을 알 수 있습니다.
00:13:18따라서 이 트랜스포머 레이어 내부에서 무슨 일이 일어나는지 살펴볼 가치가 있습니다.
00:13:24트랜스포머 레이어 안에는 더 많은 하위 레이어들이 존재합니다.
00:13:28정규화 레이어가 있고,
00:13:30어텐션 레이어가 있으며,
00:13:32피드 포워드 레이어 등이 있습니다.
00:13:35그중에서도 어텐션 레이어가 매우 유명해졌다고 생각합니다.
00:13:40어텐션이 전부라는 논문의 저자들처럼 말이죠.
00:13:42다들 잘 알고 계실 겁니다.
00:13:44어텐션은 연산량이 가장 많은 레이어입니다.
00:13:48따라서 우리는 그 어텐션 레이어 내부에서 무슨 일이 일어나는지 이해해야 합니다.
00:13:53어텐션은 과연 어떤 역할을 할까요?
00:13:56입력 텍스트가 있을 때, 모든 이전 토큰들에 대한 각 토큰의 어텐션 점수를 찾아내야 합니다.
00:14:05이를 위해 각 토큰을 키, 쿼리, 그리고 밸류 공간으로 각각 투영해야 합니다.
00:14:14더 알기 쉽게 간단히 설명하자면 이렇습니다.
00:14:20토큰이 10개라면, 10개의 서로 다른 쿼리, 키, 밸류 벡터가 필요합니다.
00:14:26토큰이 100개라면 100개의 키와 밸류 벡터가 필요하겠죠.
00:14:31토큰이 1000개라면 1000개의 키 밸류 벡터가 필요합니다.
00:14:35즉, 입력 크기가 커질수록 키와 밸류 벡터의 수도 함께 증가합니다.
00:14:45미스트랄 7B의 토큰당 KV 크기를 계산해보면 131바이트 정도가 됩니다.
00:14:54K와 V라는 두 개의 벡터가 존재하기 때문입니다.
00:14:59크기를 곱해 계산해야 하죠.
00:15:02벡터 하나는 128차원입니다.
00:15:04이를 32개의 트랜스포머 레이어 수만큼 곱해야 합니다.
00:15:08그런 다음 KV 헤드 수와도 곱해줘야 하죠.
00:15:11미스트랄 7B의 KV 헤드 수는 그렇습니다.
00:15:1532개와는 다르죠. 다른 방식의 어텐션 메커니즘을 사용하기 때문인데, 이 부분은 확실히 짚고 넘어가겠습니다.
00:15:23아무튼 토큰당 KV 크기는 대략 131 정도 됩니다.
00:15:30이제 4K 컨텍스트를 사용한다고 상상해 보면, 그 크기는 약 0.5GB가 됩니다.
00:15:3716K 컨텍스트를 사용하면 크기가 2.1GB로 늘어납니다.
00:15:42여기에 사용자 수를 곱해 보세요.
00:15:45여러 사용자를 동시에 서비스한다고 가정해 봅시다.
00:15:494K 컨텍스트와 80명의 사용자가 있다면 GPU 내에서 42GB를 차지할 수 있습니다.
00:15:58만약 GPU 용량이 24GB에 불과하다면 이미 메모리가 부족해지기 시작하죠.
00:16:04따라서 그만큼 많은 컨텍스트로 많은 사용자를 서비스할 수 없게 됩니다.
00:16:11이를 시각적으로 확인하기 위해 GPU 메모리를 살펴보겠습니다.
00:16:14GPU 메모리에는 꽤 고정되어 있는 모델 가중치가 있습니다.
00:16:19이것은 사전 학습된 가중치입니다.
00:16:21또한 고정된 오버헤드도 존재합니다.
00:16:24오버헤드 역시 변하기는 하지만 그렇게 크게 변하지는 않습니다.
00:16:29전체적으로 고정되어 있다고 볼 수 있죠.
00:16:32그리고 남은 메모리가 있습니다.
00:16:35이 남은 메모리가 바로 KV 메모리, 즉 키와 밸류 벡터에 의해 사용되는 공간입니다.
00:16:41사용자가 한 명 있다고 가정해 봅시다.
00:16:46남아 있는 전체 80GB 메모리에 들어맞을 만큼의 키와 밸류 벡터, 혹은 그만큼의 토큰만 서비스할 수 있습니다.
00:17:00간단한 데모를 통해서도 이를 보여드릴 수 있습니다.
00:17:07좋습니다.
00:17:08좋습니다.
00:17:08실제로 실행할 수 있는지 한번 확인해 보겠습니다.
00:17:14좋습니다.
00:17:15실제로 실행할 수 있는지 확인해 볼게요.
00:17:15이게 도대체 어디 있죠?
00:17:15좋습니다.
00:17:16실제로 실행할 수 있는지 확인해 보겠습니다.
00:17:21이게 도대체 어디 있는 거지?
00:17:22좋습니다.
00:17:23좋습니다.
00:17:24네.
00:17:25네.
00:17:25보시다시피... 실제로 실행할 수 있는지 확인해 보겠습니다.
00:17:31실제로 실행할 수 있는지 확인해 보겠습니다.
00:17:33한번 실행해 보죠.
00:17:34한번 실행해 보겠습니다.
00:17:35한번 실행해 보죠.
00:17:36한번 실행해 보겠습니다.
00:17:37좋습니다.
00:17:38네.
00:17:39보시다시피 GPU가 연결되어 있습니다.
00:17:43좋습니다.
00:17:44네.
00:17:45보시다시피 GPU가 연결되어 있죠.
00:17:56여기서는 우리가 세운 수식과 직관을 바탕으로 메모리를 확인해 보려고 합니다.
00:18:13우리가 구축한 직관 말이죠.
00:18:14모델 메모리의 경우, 예를 들어 70억 개의 파라미터가 있고
00:18:1916비트 정밀도를 사용한다고 가정해 봅시다.
00:18:20총 메모리는 14.6GB가 나옵니다.
00:18:23수식을 통해 기본적으로 이를 검증할 수 있습니다.
00:18:27그 모든 수식을 계산해보면 14.6GB가 나오죠.
00:18:33이제 KV와 KV 크기에 대해 이야기해 보겠습니다.
00:18:37이 KV 크기는 토큰당 131 정도입니다.
00:18:42수식을 계산하고 이를 시각화해보면 됩니다.
00:18:47아, 물론입니다.
00:18:52잠시만요.
00:18:53좋습니다.
00:18:54그럼 이를 시각화해 보겠습니다.
00:19:07좋습니다.
00:19:10좋습니다.
00:19:11네.
00:19:12이것이 바로 메모리 차트입니다.
00:19:15보시다시피 컨텍스트가 증가할수록 메모리도 계속 증가합니다.
00:19:21그리고 또 한 가지 깨달아야 할 점은 사용자가 늘어날수록 메모리도 함께 증가한다는 것입니다.
00:19:28따라서 하나의 GPU에서 160명의 사용자를 서비스하고 싶다면, 지원할 수 있는
00:19:37컨텍스트 길이는 더 짧아질 수밖에 없습니다.
00:19:40결국 제공할 수 있는 컨텍스트 길이와, 여러 사용자 또는 동시 사용자를
00:19:47하나의 GPU에 수용함으로써 절약할 수 있는 비용 사이에는 항상 상충 관계가 존재합니다.
00:19:54따라서 항상 이러한 트레이드오프를 고려해야 합니다.
00:19:57이 내용은 몇 가지 슬라이드를 더 보면서 살펴보겠습니다.
00:20:06다시 말씀해 주시겠어요?
00:20:10죄송합니다.
00:20:11목소리가 잘 안 들립니다.
00:20:12컨텍스트 길이가 다른 별도의 풀을 두어 적절한 메모리를 서비스할 수 있도록
00:20:25고려하시나요?
00:20:26네.
00:20:27좋습니다.
00:20:28좋습니다.
00:20:29알겠습니다.
00:20:30좋습니다.
00:20:31그럼 다시 돌아가서요.
00:20:32아까 메모리 이야기였습니다.
00:20:33컨텍스트 길이를 늘렸을 때 첫 번째 토큰 생성 시간이 왜 더 느려졌는지 이해해야 합니다.
00:20:53길이 말이죠.
00:20:54이를 위해 추론의 두 가지 단계를 이해할 필요가 있습니다.
00:20:58그 단계는 바로 프리필(pre-fill) 단계와 디코드(decode) 단계입니다.
00:21:01관련된 글들을 많이 보셨겠지만, 여기서 다시 한번 설명해 드리려고 합니다.
00:21:06많은 입력 토큰을 보낼 때 우리가 하고 싶은 것은, 앞서 언급했던 모든 토큰에 대한 키와 밸류 벡터를 구축하는 것입니다.
00:21:20그런 다음 이전 토큰들에 대한 각 토큰의 어텐션 점수를 계산해야 합니다.
00:21:27이러한 모든 작업은 행렬 연산이 매우매우 많이 들어갑니다.
00:21:31연산 부하가 엄청나게 큰 작업이죠.
00:21:34우리도 잘 알듯이 GPU는 무거운 연산 워크로드에 매우 적합합니다.
00:21:41그래서 프리필 단계를 연산 집약적(compute-bound)이라고 부릅니다.
00:21:46완료되는 데 어느 정도 시간이 걸릴 수밖에 없습니다.
00:21:49따라서 이 단계가 완료되는 데 걸리는 시간이 바로 첫 번째 토큰 생성 시간(TTFT)이 됩니다.
00:21:55입력 토큰이 더 많다면, 더 많은 키 밸류 벡터를 생성해야 합니다.
00:22:02훨씬 더 많은 어텐션 연산을 수행해야 하죠.
00:22:05그로 인해 TTFT가 점점 더 느려지게 됩니다.
00:22:12반면에 토큰을 하나 생성한 후에는, 다른 토큰들을 생성하기 위해 이를 계속해서 순차적으로 반복해야 합니다.
00:22:20하지만 그 과정에서 매번 이전의 모든 토큰에 대한 키 및 값 벡터를 구축해야 하는데, 이는 프리필 단계와 같습니다.
00:22:30프리필 단계에서도 키 값 벡터를 구축했던 것처럼 여기서도 마찬가지입니다.
00:22:34하지만 디코드 단계에서는 새로운 토큰에 대한 어텐션 연산만 수행합니다.
00:22:40그렇기 때문에 연산 비중이 훨씬 더 적습니다.
00:22:45또한 이를 메모리 바운드라고도 부릅니다.
00:22:48왜 메모리 바운드라고 부르는지 곧 살펴보겠습니다.
00:22:54따라서 전형적인 타임라인에서는 프리필과 디코드 단계를 이와 같이 볼 수 있습니다.
00:22:59프리필이 소요하는 시간이 곧 첫 번째 토큰 생성 시간(TTFT)입니다.
00:23:03그리고 각 디코드 단계가 소요하는 시간은 기본적으로 토큰 간 지연 시간(inter-token latency)이 됩니다.
00:23:12이것이 여러분이 신경 써야 할 네 번째 지표입니다.
00:23:18디코드 단계에서 소요되는 시간이 얼마나 되는가 하는 점입니다.
00:23:21좋습니다.
00:23:22좋습니다.
00:23:23좋습니다.
00:23:24그렇다면 디코드 단계는 왜, 무엇 때문에 시간이 오래 걸릴까요?
00:23:34그리고 왜 메모리 바운드 연산이라고 불리는 걸까요?
00:23:38그 이유를 이해해 봅시다.
00:23:40이를 이해하기 위해 GPU에서 행렬 연산이 개략적으로 어떻게 작동하는지 살펴볼 필요가 있습니다.
00:23:47GPU에는 두 가지 종류의 메모리가 있습니다.
00:23:50고대역폭 메모리(HBM)가 있습니다.
00:23:52그리고 공유 메모리가 있습니다.
00:23:55고대역폭 메모리는 용량은 더 크지만 대역폭은 더 낮습니다.
00:24:01대역폭이 낮다는 것은 거기서 데이터를 전송하는 속도가 더 느리다는 뜻입니다.
00:24:06공유 메모리와 비교했을 때 그렇습니다. 공유 메모리는 용량은 더 작지만 대역폭이 매우 매우 높습니다.
00:24:13즉, 데이터를 안팎으로 매우 빠르게 전송할 수 있다는 뜻입니다.
00:24:19따라서 행렬 연산을 수행해야 할 때는 고대역폭 메모리에서 데이터를 청크 단위로 가져와야 합니다.
00:24:27이를 공유 메모리에 올려야 합니다.
00:24:30그리고 연산을 수행합니다.
00:24:32결과를 다시 고대역폭 메모리에 기록합니다.
00:24:38프리필 단계에서는 이 작업을 수행해야 할 때, 이 행렬 연산을 단 한 번만 수행하면 됩니다.
00:24:46하지만 디코드 단계에서는 모든 토큰을 하나씩 순차적으로 생성하기 때문에 이 행렬 연산을 계속해서 반복해야 합니다.
00:24:59그렇기 때문에 디코드 속도가 얼마나 빠른지는 중요하지 않습니다. 이제 고대역폭 메모리에서 공유 메모리로 데이터를 특정 속도로만 전송할 수 있기 때문입니다.
00:25:14고대역폭 메모리의 대역폭 속도에 제한을 받기 때문입니다.
00:25:18결과적으로 이것이 토큰 생성의 상한선을 결정하게 됩니다. 즉, 디코드 단계에서 실제로 토큰을 어느 정도의 속도로 생성할 수 있는지가 결정되는 것입니다.
00:25:32이를 루프라인 플롯(roofline plot)에서 살펴보면, 메모리 바운드라고 불리는 왼쪽 영역이 존재합니다.
00:25:42수학적으로 이는 연산 강도(arithmetic intensity)에 의해 좌우됩니다.
00:25:47연산 강도란 전송되는 데이터 1바이트당 수행하는 부동소수점 연산의 횟수를 의미합니다.
00:25:55따라서 디코드 단계의 경우, 이전 모든 토큰의 키 및 값 벡터, 그리고 모델 가중치와 같은 많은 데이터를 전송해야 하므로,
00:26:08단 하나의 토큰에 대해서만 어텐션 연산을 수행하기 때문에 연산량은 상대적으로 적습니다.
00:26:13그래서 연산 강도가 매우 낮습니다.
00:26:18하지만 프리필 단계에서는 데이터를 한 번 전송한 다음, 이러한 무거운 연산을 수행하게 됩니다.
00:26:27따라서 연산 강도가 매우 높습니다.
00:26:30이제 수학적 관점에서 왜 프리필의 연산 강도가 디코드에 비해 매우 높은지 이해하셨을 겁니다.
00:26:44좋습니다.
00:26:46이것은 또 다른 작고 간단한 데모입니다.
00:26:51좋습니다.
00:26:52매번 제가 해야 하는.
00:26:53좋습니다.
00:26:54좋습니다.
00:26:55좋습니다.
00:26:56이미 준비되었기를 바랍니다.
00:26:58그렇습니다.
00:26:59다시 모델을 로드하고 있습니다.
00:27:04자, 이것은 프리필 비용에 대한 내용입니다.
00:27:09따라서 우리가 기본적으로 하는 일은 입력 텍스트를 가져와서 프리필 단계와 그것이 소요하는 시간을 생성하려고 시도하는 것입니다.
00:27:22입력 토큰의 크기를 늘림에 따라 이 프리필 시간도 증가하는 것을 볼 수 있습니다.
00:27:28이것이 바로 TTFT가 증가하는 이유이며, 여러분도 잘 아실 겁니다.
00:27:33그리고 디코드 시간에 대해서도 마찬가지입니다.
00:27:36디코드 시간은 평균적으로 거의 동일하게 유지됩니다.
00:27:41따라서 콜드 스타트를 무시한다고 가정하면, 디코드 시간은 대략 평균선 주위에 위치합니다.
00:27:50그렇지만 여전히 입력 크기에 의해 영향을 받습니다.
00:27:57완전히 일정한 시간이 소요되는 것은 아닙니다.
00:28:00이전 모든 토큰에 대한 키 및 값 벡터를 여전히 메모리에서 가져와야 하기 때문입니다.
00:28:07따라서 디코드 단계에서도 시간이 소소하게 증가하는 것을 여전히 확인할 수 있습니다.
00:28:15그리고 이것이 전형적인 루프라인 플롯입니다.
00:28:20좋습니다.
00:28:22좋습니다.
00:28:23프레젠테이션.
00:28:24좋습니다.
00:28:25좋습니다.
00:28:26좋습니다.
00:28:27자, 이제 처리량(throughput) 측면에 대해 이해해 보도록 하겠습니다.
00:28:43실제로 몇 명의 사용자에게 서비스를 제공할 수 있는지 이해하고자 하는 것입니다.
00:28:48앞서 키 및 값 벡터가 커질 수 있도록 비워져 있는 메모리가 있다는 것을 GPU 메모리 다이어그램을 통해 보았다고 생각합니다.
00:28:56좋습니다.
00:28:57단 한 명의 사용자만 있다고 가정해 봅시다.
00:29:01지원할 수 있는 총 KV 크기는 얼마일까요?
00:29:09이는 컨텍스트 제한에 의해 정의됩니다.
00:29:11지원할 수 있는 최대 사용자 수는 GPU의 가용 메모리, 즉 GPU에서 사용 가능한 메모리를 사용자당 키 및 값 크기로 나눈 값입니다.
00:29:25그렇게 계산하면 동시 사용자 수가 도출됩니다.
00:29:32자, GPU가 고정되어 있고 모델이 고정되어 있어서 토큰당 KV 크기도 고정되어 있다고 가정해 보겠습니다.
00:29:46여기서 남은 차원은 컨텍스트와 동시 사용자 수, 이 두 가지뿐입니다.
00:29:53더 많은 동시 사용자에게 서비스를 제공하려면 컨텍스트 길이를 줄여야 합니다.
00:29:57컨텍스트 길이를 줄이면 품질에 영향을 줄 수 있습니다.
00:30:02결국 이것이 우리가 현재 트레이드오프를 하고 있는 두 가지 차원입니다.
00:30:09그렇다면 실제로 최대 동시 사용자 수만큼 서비스를 제공할 수 있을까요?
00:30:17이상적인 세계라면 아마 아닐 것입니다. 모든 비즈니스에는 충족해야 하는 지연 시간 서비스 수준 목표(SLO)가 있기 때문입니다.
00:30:27따라서 앞서 디코드 단계에서 말씀드렸듯이, 입력이 더 많아지면 디코드 시간도 여전히 증가합니다.
00:30:37사용자가 더 많아져도 이 시간은 증가합니다.
00:30:40결과적으로 배치 크기가 더 커지면 토큰 간 지연 시간도 영향을 받게 됩니다.
00:30:51또한 TTFT도 영향을 받습니다.
00:30:53이제 여러분이 신경 써야 할 세 번째 차원이 생겼는데, 바로 지연 시간입니다.
00:30:58가지고 있는 세 가지 차원은 품질, 지연 시간, 그리고 처리량입니다.
00:31:04결국 이들 사이에서 선택을 해야 하는 트레이드오프 삼각형이 만들어집니다.
00:31:11따라서 프리미엄 챗 애플리케이션의 경우, 품질을 확실히 우선시하고 싶을 것이며 지연 시간 또한 우선시하고 싶을 것입니다.
00:31:21사용자가 무한정 기다리게 하고 싶지는 않겠지만, 긴 지연 시간은 어느 정도 감수하려 할 것입니다.
00:31:30GPU에서 지원할 수 있는 사용자 수를 항상 희생하면서, 더 고객 집착적인 자세로 그 비용을 감수할 수 있습니다.
00:31:39그리고 에이전트, 죄송합니다. 비동기 에이전트 워크로드의 경우, 품질과 처리량을 확실하게 우선시하고 싶을 것입니다.
00:31:53이러한 작업들은 장시간 실행되는 작업이기 때문입니다.
00:31:56그리고 매우 높은 품질을 유지하면서 가능한 한 많은 동시 작업을 처리하고 싶을 것입니다.
00:32:06그리고 종종 우리는 '그래, GPU가 아주 비싼 GPU라면 우리에게 적합하지 않을지도 몰라'라고 생각하곤 합니다.
00:32:19하지만 알고 보면 그것이 실제로 백만 토큰당 가장 낮은 비용을 제공할 수도 있습니다.
00:32:27하지만 원하는 최대 사용자 수에 대한 계산을 정말 믿어야 하며, 이러한 추정치를 정확하게 수행해야 합니다.
00:32:40그래서 저희는, 잠깐만요, 아주 좋습니다.
00:32:55용량 계산기와 관련해서는, 제가 익숙했기 때문에 코랩(Colab) 링크가 있습니다.
00:33:01전체 위젯 라이브러리에서 마이그레이션을 해야 했는데 시간이 없었습니다.
00:33:16그래서 게으르게도 그냥 코랩을 선택했습니다.
00:33:20제 연구실에 사과드립니다.
00:33:23그래서 제 VRAM이 연결되어 있습니다.
00:33:34좋습니다.
00:33:45아마도 와이파이 문제겠죠.
00:33:46알겠습니다, 좋습니다.
00:34:02여기서 우리가 한 일은 여러 GPU를 VRAM, 대역폭, 부동소수점 연산 성능, 시간당 비용과 함께 정리해 둔 것입니다.
00:34:11그런 다음 이와 같은 간단한 용량 계산기를 만들었습니다.
00:34:19이것은 일종의 KV 시각화 도구로, 토큰 수를 늘리면 KV 크기가 증가하는 것을 볼 수 있습니다.
00:34:29그리고 사용자 수를 늘리면 크기가 훨씬 더 빠른 속도로 증가합니다.
00:34:37그런 다음, 이 용량 계산기를 실행해 보겠습니다.
00:34:47여기 선택한 70억(7B) 파라미터 모델 같은 모델이 있습니다.
00:34:56정밀도를 FP16으로 설정했습니다.
00:35:01이제 우리가 GPU 결정을 내리는 방식은, 가장 중요하게 생각하는 하나의 차원을 먼저 고정해야 한다는 것입니다.
00:35:15따라서 프리미엄 챗의 경우 지연 시간이 확실히 그 대상이라고 말씀드렸습니다.
00:35:21그리고 비동기 워크로드의 경우, 단일 GPU에서 처리하고자 하는 최소 배치 크기가 두 번째 차원이 됩니다.
00:35:31따라서 이것들을 먼저 고정해야 합니다.
00:35:34그러면 프리미엄 챗 애플리케이션의 경우를 가정해 보겠습니다.
00:35:39대략 10밀리초의 지연 시간으로 진행할 수 있습니다.
00:35:44최소 배치 크기는 상관없습니다.
00:35:46대략 2 정도여도 괜찮습니다.
00:35:53좋습니다.
00:35:54단일 GPU에서 동시 사용자 7명 정도가 되겠네요.
00:35:59그리고 품질에도 집중하고 싶기 때문에 컨텍스트 제한이 매우 중요합니다.
00:36:07그래서 일부 GPU들을 살펴보게 됩니다.
00:36:10H100 80GB의 경우 시간당 8달러 정도입니다.
00:36:15하지만 제 300x는 어떨까요?
00:36:19그렇나요?
00:36:20네.
00:36:21대략 시간당 10달러 정도죠.
00:36:24따라서 앞서 수학적으로 공유해 드린 처리량 계산을 적용해 보면 100만 토큰당 비용이 어느 정도인지 산출할 수 있습니다.
00:36:34비용을 훨씬 더 낮출 수 있죠.
00:36:37그러므로 이러한 차원들을 고정한 상태에서 계산을 수행하고, 일종의 추론 비용을 줄이기 위해 적절한 GPU를 선택해야 합니다.
00:36:49이것이 적어도 추론 최적화를 위해 취할 수 있는 첫 번째 단계입니다.
00:36:56알겠습니다.
00:37:01자, 다음 슬라이드로 넘어가겠습니다.
00:37:04잠시만요.
00:37:08좋습니다.
00:37:10자, 이제 다음 주제는 모델 최적화에 관한 것입니다.
00:37:15우리는 이제 일부 문제점들과 그러한 문제점이 발생한 원인, 그리고 그 이유를 이해하는 기반을 다졌습니다.
00:37:23GPU 용량 문제를 어떻게 해결할 수 있을지 이야기해 보았죠.
00:37:29이제 그 외에 무엇을 더 할 수 있는지 이해해야 합니다.
00:37:33바로 모델 최적화에 대한 내용인데, 탄마이(Tanmay)님을 초대하고 싶습니다.
00:37:39탄마이님은 연구 시절 이와 관련된 작업을 하셨기 때문에 모델 최적화에 대해 더 자세히 말씀해 주실 수 있을 겁니다.
00:37:47좋습니다.
00:37:48좋습니다.
00:37:49제가 화면을 넘기겠습니다.
00:37:50제가 제어할게요.
00:37:54네.
00:37:55여기서요.
00:37:56알겠습니다.
00:37:57안녕하세요 여러분.
00:37:58마이크 테스트입니다.
00:37:59드디어 제 목소리가 들리나요?
00:38:00네.
00:38:01좋습니다.
00:38:02안녕하세요.
00:38:03저는 탄마이 샤(Tanmay Shah)입니다.
00:38:04시니어 퀀트 모델러로 일하고 있고, AI 연구원이기도 합니다.
00:38:08주로 에이전트 검증에 초점을 맞추고 있으며, 현재는 세계 모델(world model)을 구축하고 있습니다.
00:38:13이번 주제는 모델 최적화입니다.
00:38:16모델 최적화를 시작하기에 앞서, 이 모든 복잡한 내용을 쉽게 이해할 수 있도록 연구 템플릿을 하나 만들었습니다.
00:38:25저희 템플릿은 간단합니다.
00:38:28첫째, 문제를 식별합니다.
00:38:30둘째, 두 가지 알고리즘을 사용해 문제를 해결합니다.
00:38:34이것은 가상의 알고리즘일 뿐입니다.
00:38:35첫 번째 알고리즘은 타조 알고리즘(ostrich algorithm)이라고 부릅니다.
00:38:39타조처럼, 문제가 나타나면 타조가 모래 속에 머리를 파묻는 것과 같습니다.
00:38:46우리도 똑같이 할 겁니다.
00:38:47문제에 직면할 때마다 그냥 무시해 버리는 거죠.
00:38:51이것이 우리가 따라야 할 중요한 알고리즘입니다.
00:38:55두 번째로 만든 것은 월드컵 알고리즘이라고 합니다.
00:38:59예를 들어, 이번 FIFA 월드컵에서 누가 우승할지 우리는 모릅니다.
00:39:03그래서 주최측은 48개 팀을 12개 조로 나누었습니다.
00:39:11그런 다음 32강전을 치르고, 현재는 32강전이 진행 중이죠.
00:39:16그다음에 16강, 8강, 4강, 그리고 결승전으로 이어집니다.
00:39:21그들이 하는 일은 문제를 더 작은 문제로 쪼개고, 유용한 결과물들을 다음 단계로 진출시키는 것입니다.
00:39:30이 모델 최적화와 모든 과정들을 이해하기 위해 이와 동일한 비유와 알고리즘을 사용할 것입니다.
00:39:38그럼 시작해 볼까요.
00:39:41자, 제게 H100 GPU가 하나 있습니다.
00:39:46이 오픈소스 모델을 사용해야 하는데, GPT OSS 120B(1200억) 파라미터 모델이라고 불리는 것입니다.
00:39:54현재 제 생각에는 BF16으로 학습되었고 가중치 용량이 240기가바이트입니다.
00:40:02어떻게 해야 할까요?
00:40:04이것이 우리 앞에 놓인 문제입니다.
00:40:07첫 번째로 해야 할 일은, 모델은 240기가바이트인데 H100은 80기가바이트라는 점입니다.
00:40:16여러 개의 GPU가 아니라 오직 하나의 GPU에만 모델을 올려야 합니다.
00:40:21그렇다면 무엇을 할 수 있을까요?
00:40:22제 생각에 간단한 방법은 그냥 압축하는 것입니다.
00:40:27하지만 어떻게 압축해야 할까요?
00:40:29이것이 또 다른 과제입니다.
00:40:30만약 BF16을 FP8로 압축하면, 크기가 약 120기가바이트가 될 것입니다.
00:40:38하지만 우리의 H100 GPU는 여전히 80기가바이트 용량입니다.
00:40:42그래서 그들은 한 걸음 더 나아가 MXFP4로 압축한 것으로 생각합니다.
00:40:49그렇게 하면 크기가 약 65기가바이트 정도가 됩니다.
00:40:53이것이 바로 우리가 할 수 있는 압축 방식이지만, 의문이 생깁니다.
00:40:59여기서 우리는 타조 알고리즘을 적용할 겁니다.
00:41:03더 큰 모델을 더 작은 크기로 압축할 때 손실이 전혀 없다고 가정하는 것이죠.
00:41:10두 번째로, 이 슬라이드에서, 아 네.
00:41:16이 슬라이드에서는 미스트랄 7B(Mistral 7B)를 사용했습니다.
00:41:2070억 개의 파라미터죠.
00:41:2270억 파라미터의 작은 모델입니다.
00:41:25여기에 2바이트를 곱해보면, 모델의 가중치 용량은 대략 14...
00:41:3114.5기가바이트가 되며, 이는 H100이나 심지어 A40에도 쉽게 들어갈 수 있습니다.
00:41:38다음으로 미스트랄 7B를 16비트 부동소수점으로 유지하는 대신, INT8, INT4, NF4 같은 다양한 기법을 적용할 수 있습니다.
00:41:53기본적으로 타조 알고리즘을 사용해 품질 저하 같은 것은 전혀 없다고 믿어버리면 됩니다.
00:42:01하지만 어떻게든 외부 벤치마크 테스트를 통해 제대로 작동하는지 수학적으로 증명해야 하기도 합니다.
00:42:10이러한 과정은 사후 학습 양자화(post-training quantization) 범주에 속합니다.
00:42:16파인튜닝을 진행하는 동안에도 이를 수행할 수 있습니다.
00:42:20이러한 종류의 양자화를 수행할 수도 있죠.
00:42:22이것은 양자화 인지 학습(quant-aware training)에 해당합니다.
00:42:25자, 다음 문제로 넘어가겠습니다.
00:42:31우리에겐 거대한 행렬들이 있습니다.
00:42:371000 곱하기 1000 차원의 행렬 A와, 또 다른 1000 곱하기 1000 행렬을 상상해 보세요.
00:42:51이 두 행렬을 곱하면 연산 횟수는 1000의 세제곱이 됩니다.
00:43:00이것은 컴퓨팅 측면에서 문제가 됩니다.
00:43:06따라서 우리는 행렬 곱셈이 빠르고 메모리를 절약하기를 원합니다.
00:43:13그럼 어떻게 해야 할까요?
00:43:15우리에게는 거대한 행렬이 있습니다.
00:43:17좋습니다, 4096 곱하기 4096 크기를 예로 들어 봅시다.
00:43:234096 곱하기 4096 행렬에서 연산을 속도 높이고 메모리를 절약하기 위해 무엇을 해야 할까요?
00:43:33첫째로, 월드컵 알고리즘을 사용할 것입니다.
00:43:37임의의 숫자를 정하고 블록을 수직으로 쪼개는 겁니다.
00:43:42어떤 숫자를 선택하든 상관없습니다.
00:43:454096개의 열이 있다고 해봅시다.
00:43:51이것을 각각 128개의 열을 가진 그룹으로 쪼갭니다.
00:43:57즉, 수직으로 128, 128, 128, 128, 128씩 나누는 거죠.
00:44:03이렇게 4096을 나누면 32개의 블록을 얻게 됩니다.
00:44:09그렇다면 이렇게 했을 때 어떤 일이 벌어질까요?
00:44:13이렇게 수직으로 분할하기만 하면 여러 개의 GPU를 사용하여 프로세스 속도를 높일 수 있습니다.
00:44:21이러한 방식을 멀티 헤드 어텐션(multi-head attention)이라고 부릅니다.
00:44:26그렇다면 또 무엇을 할 수 있을까요?
00:44:29앞서 언급했듯이 타조 알고리즘 같은 큰 행렬이 있습니다.
00:44:36우리의 주된 문제는 크기(sizing)입니다.
00:44:39따라서 32개의 수직 블록을 모두 유지하는 대신, 31개의 블록을 갖다 버리는 겁니다.
00:44:49그리고 단 하나의 블록만으로도 모든 쿼리를 처리하기에 충분하다고 가정하는 것이죠.
00:44:57성능 손실은 거의 무시할 수 있을 정도일 겁니다.
00:45:00그렇게 도출된 알고리즘이 있습니다.
00:45:04이 알고리즘을 멀티 쿼리 어텐션(multi-query attention)이라고 부릅니다.
00:45:08보시다시피, 현재 우리는 양극단에 서 있습니다.
00:45:12하나는 32개의 블록으로 쪼개서 서로 다른 GPU를 사용하거나 병렬 처리를 수행하는 멀티 헤드 어텐션이고,
00:45:22동시에 31개의 블록을 그냥 내다 버리는 방식도 있습니다.
00:45:26이것을 멀티 쿼리 어텐션이라고 부르는 것이죠.
00:45:31따라서 양쪽 극단 사이에서 어떤 중간 지점을 찾아야 합니다.
00:45:3831개를 전부 버리는 대신, 블록 중 일부를 그룹으로 묶을 수 있다고 말할 수 있습니다.
00:45:49그리고 유사한 블록들은 유사한 종류의 쿼리에 집중할 것이라고 가정하는 겁니다.
00:45:58이러한 기술이 바로 현재 매우 대중적인 그룹드 쿼리 어텐션(grouped-query attention)에 해당합니다.
00:46:04미스트랄이나 다른 모델들에서도 이 그룹드 쿼리 어텐션이 작동합니다.
00:46:11자, 이제 우리는 거대한 행렬을 갖고 있다는 것을 이해했습니다.
00:46:16원하는 대로 행렬을 나누고 약간의 수학적 계산을 거쳐,
00:46:19손실이 거의 무시할 수준이라는 것을 증명할 수 있습니다.
00:46:23그렇다면 또 무엇을 할 수 있을까요?
00:46:25그 후에, 이 그룹드 쿼리 어텐션 다음에는,
00:46:34보시다시피 우리에게는 거대한 행렬이 있습니다.
00:46:38하나는 키(key) 행렬이고 다른 하나는 밸류(value) 행렬입니다.
00:46:42그 행렬을 잠재 벡터(latent vector)로 압축해 봅시다.
00:46:47그런 다음 잠재 벡터로부터 원래 행렬을 재구성하는 알고리즘을 고안해 내는 겁니다.
00:46:55이러한 전략이 바로 여기에 속합니다.
00:46:59멀티 헤드 잠재 어텐션(multi-head latent attention)이죠.
00:47:02하지만 RoPE(Rotary Position Embedding)와 관련해서 또 다른 문제가 발생합니다. RoPE는 위치 종속적인 반면 이것은 위치 독립적인 측면이 있기 때문입니다.
00:47:10따라서 매핑이 가능하도록 키(key)에 대해서도 일부 인덱스를 포함해야 합니다.
00:47:16하지만 여전히 근본적인 문제는 왜 우리가 그토록 커다란 행렬들을 곱하고 있느냐는 것입니다.
00:47:25그 이유는 어텐션 메커니즘의 작동 방식 자체가 모든 토큰이 모든 토큰에 주의를 기울이기 때문입니다.
00:47:33그렇다면 이전의 모든 토큰에 주의를 기울이는 대신, 우리에게 중요한 토큰에만 주의를 기울이는 것은 어떨까요?
00:47:42그래서 이런 분야가 계속 발전하고 있습니다.
00:47:46이는 스파스(Sparse), 딥시크 스파스 어텐션에 해당합니다.
00:47:51그렇죠.
00:47:53네, 그럼 좋습니다.
00:47:56다음으로 넘어가죠.
00:47:59네, 다음은 플래시 어텐션입니다.
00:48:02플래시 어텐션에서 핵심적인 문제는 바로,
00:48:09현재는 거의 모든 사람이 플래시 어텐션을 사용하지만, 2022년이나 2023년 당시에는 방식이 달랐다는 점입니다.
00:48:20원래는 이런 식으로 작동했습니다.
00:48:23Q와 K, 즉 쿼리 및 키 행렬이 HBM(고대역폭 메모리)에 있었습니다.
00:48:34먼저 텐서 코어로 로드되어 연산을 수행한 다음, 다시 HBM에 기록하는 방식이었죠.
00:48:47그리고 이 과정이 여러 번 반복됩니다.
00:48:51플래시 어텐션이 취한 방식은 전체 행렬을 그대로 곱하는 대신,
00:48:59큰 행렬을 작은 타일로 쪼개는 방식으로 처리하는 것입니다.
00:49:05그리고 그 작은 타일들만 SRAM에 올려서 빠른 연산이 가능하게 하고,
00:49:13온라인 소프트맥스를 계산하기 위해 세 가지 변수를 계속 추적하는 방식입니다.
00:49:20네, 수학적인 내용인데요. 멀티 헤드 어텐션이 있고 KV가 524개라면,
00:49:34원하는 그룹화 수준에 따라 달라집니다. 32개의 KV 헤드 대신 8개의 KV 헤드만 사용하고 싶다면,
00:49:474배의 압축 효과를 얻을 수 있으며, 이것이 멀티 헤드 레이턴트 어텐션입니다.
00:49:54이 공식을 적용할 때는 모델마다 레이어 개수가 다르므로 모델별 차이가 있습니다.
00:50:00원래 딥시크 논문에서는 차원이 128이었나... 정확한 차원은 기억나지 않지만, 그에 따르면
00:50:11512차원의 하나의 레이턴트 벡터와 RoPE 인덱스를 위한 64차원을 사용했다고 합니다.
00:50:23이를 통해 멀티 헤드 어텐션보다 56배 더 압축되었다는 점을 보여주었습니다.
00:50:32좋습니다.
00:50:33네, 이것이 트레이드오프 다이어그램인데요. 여기서는 선형 어텐션이나 맘바(Mamba)에 대해 아직 다루지 않은 것 같네요.
00:50:50핵심 문제는 모든 행렬 곱셈입니다. 현재는 모두가 어텐션을 사용하고 있죠.
00:50:56만약 미래에 어텐션을 사용하고 싶지 않다면, 토큰을 순차적으로 생성하는 대신 모든 것을 동시에 생성할 수 있는 확산 모델(Diffusion model) 등을 사용할 수도 있을 겁니다.
00:51:07그러면 이 모든 알고리즘도 바뀌게 되겠죠.
00:51:14하지만 여기서는 선형 어텐션과 맘바라는 두 가지가 더 언급된 것 같습니다.
00:51:19이 슬라이드에 따르면, 아무것도 압축하지 않는 MHA는 그냥 프로세스를 병렬화하는 것입니다.
00:51:29품질 저하가 없기 때문에 좋고, 그 다음은 그룹드 쿼리 어텐션인데, 현재 거의 모든 모델이 GQA와 DSA 방식을 사용하고 있습니다.
00:51:42네.
00:51:43어텐션 메커니즘 스코어카드에서도 비슷한 내용을 제공하고 있습니다. MHA는 품질이 좋고 처리량(throughput)도 괜찮은 편입니다.
00:51:56그룹드 쿼리 어텐션의 경우 사용 사례에 따라 다릅니다. 품질은 멀티 헤드 어텐션과 거의 유사하지만 사용 사례 역시 매우 중요합니다.
00:52:10네, 멀티 쿼리 어텐션은 한쪽 극단에 있는 방식입니다.
00:52:13이유는 잘 모르겠지만, 오직 하나의 블록만 필요하고 모든 쿼리가 그 더 작은 블록을 참조한다고 가정하는 것이죠.
00:52:24그래서 MQA는 품질이 그렇게 뛰어나지는 않습니다.
00:52:29그리고 멀티 헤드 레이턴트 어텐션의 경우, 딥시크 모델들을 써보셨다면 아시겠지만 슬라이딩 윈도우 외에도 품질 면에서 훌륭한 성능을 보여줍니다.
00:52:44이 모든 것들이 윈도우를 조정하는 등의 기법들입니다. 선형 어텐션은 모든 것을 먼저 요약한 뒤 참조하자는 방식이고, 맘바는 상태 공간 모델(State-space model)입니다.
00:53:09모델 최적화를 위해 여기 두 개의 노트북(코드)도 준비되어 있습니다.
00:53:28여기로 이동해야겠네요.
00:53:35좋습니다. 양자화 데모를 볼까요? 이건 이미 실행되었나요? 아닙니다.
00:53:51한 번 실행해 보겠습니다.
00:53:54자, 미스트랄(Mistral) 7B 같은 모델을 로드하고 있습니다.
00:54:10이건 FP16 베이스라인을 사용하는 버전입니다.
00:54:20잠시만요.
00:54:21실행되었나요?
00:54:21잠시만요.
00:54:22실행되었나요?
00:54:23좋습니다.
00:54:242밀리초 만에 실행되었습니다.
00:54:27이것도 실행되었나요?
00:54:28좋습니다.
00:54:29이번에는 FP16 정밀도로 모델을 가져오고 있습니다.
00:54:35좋습니다.
00:54:362밀리초 만에 실행되었습니다.
00:54:40이것도 실행되었나요?
00:54:41좋습니다.
00:54:42이번에는 FP16 정밀도로 모델을 가져오고 있습니다.
00:54:47와이파이 때문에 말이죠.
00:54:58시간이 좀 걸릴 겁니다.
00:55:03알겠습니다.
00:55:08허깅 페이스에서 가중치를 다운로드하고 있기 때문에 시간이 걸립니다.
00:55:14어?
00:55:17네, 코랩(Colab)은 온라인으로 실행되니까요.
00:55:22네.
00:55:23허깅 페이스에 네트워크 요청을 보내서 가져와야 하기 때문입니다.
00:55:30다운로드하는 데 시간이 좀 걸리는 것 같네요.
00:55:35알겠습니다.
00:55:36알겠습니다.
00:55:37알겠습니다.
00:55:38알겠습니다.
00:55:39알겠습니다.
00:55:40여기서 보시다시피 FP16 정밀도에서의 메모리 크기는 대략 15GB 정도입니다.
00:56:00우리는 탈무드가 이야기했던 것 처럼 INT8을 이용해 2배 압축을 시도하고 있습니다.
00:56:15알겠습니다.
00:56:16보시다시피 메모리 크기가 이제 0.7GB, 0.5GB 정도로 줄어듭니다.
00:56:21이것이 의미하는 바는 KV가 성장할 수 있는 메모리 여유가 더 생긴다는 뜻입니다.
00:56:27즉, 더 긴 컨텍스트 제한을 처리하거나 더 많은 동시 사용자를 수용할 수 있게 된다는 의미죠.
00:56:36INT4를 사용하면 기본적으로 4배 압축을 수행하게 됩니다.
00:56:41따라서 4배 압축을 거치면 메모리가 훨씬 더 줄어듭니다.
00:56:453~4GB 정도가 되겠네요.
00:56:50네, 4.5GB 정도입니다.
00:56:51그리고 네.
00:56:52잠시만요.
00:56:53이것은 기본적인 그래프로, 대략적인 이론상의 수치입니다.
00:57:09여기서 별도의 처리량 테스트를 진행하는 것은 아닙니다.
00:57:12하지만 보통 메모리가 늘어나면...
00:57:15처리량도 약간 더 높아지게 됩니다.
00:57:21저희가 연구한 일부 벤치마크에 따르면 INT8 압축의 경우,
00:57:26처리량이 오히려 약간 낮아지기도 합니다.
00:57:32알겠습니다.
00:57:33그리고 어텐션 메커니즘에 대한 데모가 있습니다.
00:57:42어텐션에 관해서는, 알겠습니다.
00:57:45이걸 실행해야겠네요.
00:57:58좋습니다.
00:57:59실행되었습니다.
00:58:02어.
00:58:03잠깐만요.
00:58:04왜 GPU가 감지되지 않는다고 나오죠?
00:58:09GPU가 감지되어야 하는데요.
00:58:18아.
00:58:19그렇군요.
00:58:29잠깐만요.
00:58:30잠깐만요.
00:58:30잠깐만요.
00:58:50이거 의외네요.
00:58:57무슨 이유에서인지 GPU를 감지하지 못하는 것 같습니다.
00:59:05분명 여기에 GPU가 있는데 말이죠.
00:59:11알겠습니다.
00:59:12신경 쓰지 마세요.
00:59:14네.
00:59:14여기서 기본적인 아이디어는 멀티 헤드에서 그룹드 쿼리 어텐션, 그리고 MLA로 서로 다른 어텐션 메커니즘을 사용해 연산을 압축하는 방향으로 이동함에 따라,
00:59:26일부 최적화 효과를 눈으로 확인할 수 있게 된다는 것입니다.
00:59:33어젯밤에 벤치마킹을 좀 해봤는데요.
00:59:38이 부분은 정정하고 싶습니다.
00:59:4356배가 아니었습니다.
00:59:4514배였습니다.
00:59:4814배였어요.
00:59:50기본적으로 데모 계산 과정에서 레이어 수를 곱하지 않는 실수가 있었습니다.
01:00:02네.
01:00:03이 점은 사과드립니다.
01:00:04따라서 이 MLA는 멀티 헤드 어텐션에 비해 약 14배의 절감 효과가 있습니다.
01:00:15이제 페인 포인트(고충), 기초 개념, 그리고 모델 최적화 측면을 이해했으니, 서빙 측면에서는 무엇을 할 수 있는지 이야기해 보겠습니다.
01:00:31첫 번째로, 간단한 디코딩 단계를 수행할 때 모델 가중치를 불러오고 이전의 모든 토큰에 대한 키 및 값 벡터를 재계산하는 것을 보았습니다.
01:00:50이미 모든 토큰에 대해 해당 벡터들을 계산해 두었는데도 말이죠.
01:00:55따라서 분명 연산 낭비가 상당히 많습니다.
01:01:02시간 복잡도를 분석해 보면 O(N^2)이 나오게 됩니다.
01:01:07이를 해결하는 방법은 메모리와의 고전적인 트레이드오프입니다.
01:01:12토큰에 대응하는 이 벡터들을 메모리에 유지하고 해당 메모리를 참조하는 것이죠.
01:01:19그 메모리를 KV 캐시(KVCache)라고 부릅니다.
01:01:24전체적인 흐름은 대략 이렇습니다.
01:01:27이 KV 캐시를 바탕으로 네 가지 최적화 기법이 실제로 가능해졌습니다.
01:01:35첫 번째는 페이지드 어텐션(PagedAttention)에 관한 것입니다.
01:01:42그렇다면 오늘날의 차이점과 문제점은 무엇일까요?
01:01:45즉, 여러 개의 요청을 입력으로 GPU에 보낼 때, 이 요청들은 배치로 묶이게 됩니다.
01:01:52모든 요청에는 연속된 메모리 저장소가 할당되죠.
01:01:58예를 들어, 그냥 예시를 하나 들어서, 2 KV라고 해보죠.
01:02:05하지만 여러분의 요청에 실제로 필요한 건 1 KV 정도뿐이었다고 해봅시다.
01:02:11그럼 메모리의 50% 정도가 단편화되는 셈입니다.
01:02:19그리고 이 단편화는 기본적으로 메모리 낭비로 이어지죠.
01:02:24즉, 메모리 상에는 더 많은 요청을 처리할 수 있는 공간이 있었음에도 불구하고 연속된 메모리 블록을 찾고 있었기 때문에 처리하지 못하게 됩니다.
01:02:36그래서 운영체제(OS)의 작동 방식에서 영감을 얻었습니다.
01:02:41논리 메모리를 유지하고 기본적으로 물리 메모리를 따로 두는 방식이죠.
01:02:47따라서 논리 메모리 관점에서는 모든 토큰의 KV 벡터가 마치 연속되어 있는 것처럼 느껴집니다.
01:02:59하지만 실제로는 서로 다른 물리 주소에 매핑되죠.
01:03:06이 방식은 정말 많은 메모리를 절약하는 데 도움이 되었습니다.
01:03:11그리고 메모리를 일련의 블록으로 간주했기 때문에만 가능한 일이었죠.
01:03:18요청이 필요로 하는 만큼 그 블록들을 동적으로 할당하게 됩니다.
01:03:22새로운 토큰들이 들어오고 그러한 메모리가 필요할 때 말이죠.
01:03:27또 다른 요소는, 여러 요청을 배치로 보낼 때 발생하는 문제입니다.
01:03:39GPU는 그런 요청들을 받아 처리하죠.
01:03:42하지만 해당 배치 내의 모든 요청이 완료될 때까지는 새로운 배치를 받아들이지 않습니다.
01:03:49따라서 다이어그램은 페이징 기법과 비슷해 보입니다.
01:03:52하지만 여기서는 GPU가 언제 다음 배치를 처리할 수 있는지가 더 핵심입니다.
01:03:59즉, GPU가 완전히 유휴 상태로 놀고 있는 시간대가 존재하게 되죠.
01:04:04우리는 바로 이 문제를 해결하고 싶어 합니다.
01:04:08그래서 나온 아이디어가 바로 '연속 배치(Continuous Batching)'입니다.
01:04:17연속 배치는 또한 처리량(Throughput)을 높이는 데도 큰 도움이 됩니다. 이제 더 많은 요청을 꽤 빠르게 처리할 수 있으니까요.
01:04:24GPU가 항상 바쁘게 일하고 놀지 않도록 계속해서 유지해 주는 것이죠.
01:04:33결과적으로 연산 자원을 아끼게 됩니다.
01:04:36세 번째는 바로 프리픽스 캐싱(Prefix Caching)입니다.
01:04:39앞서 KV 캐시가 단일 요청 내의 토큰들에 대한 연산을 절약해 준다고 말씀드린 것 기억하시죠?
01:04:46하지만 여러 요청에 걸쳐 동일한 토큰들이 존재한다면 어떨까요?
01:04:53그 중복을 어떻게 절약할 수 있을까요?
01:04:55VLLM에서 도입한 프리픽스 캐싱이 바로 그 문제를 정확히 해결해 줍니다.
01:05:04그리고 세 번째는... 아니, 네 번째에 대해 이야기했군요.
01:05:10모델 양자화에 대해 이야기했지만, KV 가중치도 양자화할 수 있습니다.
01:05:21즉, 이제 키와 값 벡터를 위해 더 적은 공간만 필요하다는 뜻이죠.
01:05:28이 말은 메모리에서 더 많은 키와 값 벡터를 처리할 수 있다는 의미입니다.
01:05:32결과적으로 더 많은 토큰을 처리할 수 있고,
01:05:34더 긴 컨텍스트 한계를 지원할 수 있으며,
01:05:37더 높은 모델 품질을 제공할 수 있게 됩니다.
01:05:41그리고 이 모든 기능은 이미 VLLM에 구현되어 있습니다.
01:05:51굳이 바퀴를 다시 발명할 필요가 전혀 없죠.
01:05:56이 VLLM을 프로덕션 환경에 배포하기만 하면 성능 향상을 직접 확인할 수 있습니다.
01:06:03자, 다음으로 우리가 진행한 벤치마크 결과가 있습니다.
01:06:08이 벤치마크가... 자료가 있는지 한번 확인해 볼게요.
01:06:14여기 있네요.
01:06:17데모 화면입니다.
01:06:22이 벤치마크를 실행하는 데는 약 한 시간이 걸립니다. VLLM 서버를 계속해서 중지하고 재시작해야 하며, 모델을 로드하는 등의 작업이 필요하기 때문이죠.
01:06:35테스트를 수행하는 데 꽤 많은 시간이 걸리지만, 여기서 우리가 무엇을 하고 있는지 확실히 설명해 드릴 수 있습니다.
01:06:41우선 모델은 Mistral 7B로 동일하게 유지했습니다.
01:06:46그리고 보내고자 하는 일련의 입력 질문들이 있죠.
01:06:53이것들을 프롬프트라고 생각하시면 됩니다.
01:06:56그런 다음 서버가 실행 중인지 확인하는 등의 몇 가지 도우미 함수(helper function)가 있습니다.
01:07:01여기서 서버는 VLLM 서버를 의미합니다.
01:07:04그 후 VLLM 메트릭을 가져오는 도우미 함수들도 있고요.
01:07:09이 메트릭들이 무엇을 의미하는지에 대해서도 이야기하겠습니다.
01:07:14그 외에도 많은 벤치마크 코드들이 있습니다.
01:07:17그리고 KV 사용량 등을 측정해야 하죠.
01:07:22이러한 것들이 바로 도우미 함수들입니다.
01:07:24베이스라인(기준선)은 아주 간단합니다.
01:07:26Hugging Face 베이스라인을 사용했는데요.
01:07:29이것은 LLM에 날것 그대로 텍스트를 보내고 응답을 받아오는 방식입니다.
01:07:36여기서 몇 가지 결과를 볼 수 있습니다.
01:07:38Hugging Face의 처리량은 초당 약 51개 토큰 정도라는 것을 확인했습니다.
01:07:44첫 토큰 생성 시간(TTFT)은 54였고요.
01:07:46토큰 간 지연 시간은 19였습니다.
01:07:49이 모든 테스트는 H100에서 실행되었습니다.
01:07:56그런 다음, 아주 기본 설정의 VLLM 서버를 실행합니다.
01:08:00기본적으로 VLLM은 페이징 기법, 연속 배치, 그리고 KV 캐싱을 제공합니다.
01:08:08즉, 세 가지 기능이 기본적으로 포함되어 있죠.
01:08:13이 벤치마크들을 비교해 보면, 처리량이 거의 15배 가까이 증가하는 것을 볼 수 있습니다.
01:08:21초당 더 많은 토큰을 처리할 수 있게 되는 것이죠.
01:08:24그리고 첫 토큰 생성 시간도 늘어납니다.
01:08:34토큰 간 지연 시간은 다소 줄어들고요.
01:08:38사용자 및 컨텍스트 대비 KV 캐시 사용량은 확실히 증가합니다.
01:08:43자, 여기에 프리픽스 캐싱을 적용해 보면 어떨까요.
01:08:51프리픽스 캐싱을 적용하면 처리량이 더욱 증가하는 것을 볼 수 있습니다.
01:08:57TTFT(첫 토큰 생성 시간)는 감소합니다.
01:08:59토큰 간 지연 시간은 거의 비슷합니다.
01:09:02그리고 사용자 대비 KV 캐시 사용량은 약간 감소하는 경향을 보입니다.
01:09:09컨텍스트 대비 사용량은 줄어들지 않고요.
01:09:12거의 비슷합니다.
01:09:14이 부분도 거의 비슷한 것 같네요.
01:09:16그렇게 엄청난 차이가 나는 것은 아닙니다.
01:09:19여기에 추가로 KV 양자화를 적용하면 어떻게 될까요.
01:09:25처리량은 거의 비슷하다는 것을 알 수 있습니다.
01:09:33첫 토큰 생성 시간도 비슷하고요.
01:09:36토큰 지연 시간도 비슷합니다.
01:09:39하지만 KV 사용량은 실제로 감소합니다.
01:09:42키-값 공간을 양자화했기 때문입니다.
01:09:49그리고 탄마이(Tanmay)가 이야기할 추론 가속(Speculative Decoding) 개념이 있습니다.
01:09:54이것들을 벤치마킹해 보면, KV 사용량이 약간 줄어드는 것도 확인할 수 있습니다.
01:10:06결과 자체는 대동소이하지만요.
01:10:08전반적으로 이것들이 바로 여러 조건에서의 메트릭들입니다.
01:10:21화면을 축소해야겠네요.
01:10:25좋습니다.
01:10:26안 되네요.
01:10:27축소.
01:10:28작동하지 않네요.
01:10:29참 좋습니다.
01:10:30네, 이것이 바로 VLLM 벤치마크 결과입니다.
01:10:35참고로 프로덕션 환경의 기본 설정이기도 하죠.
01:10:38다른 엔진들에 대해 이야기할 때 이 의사 결정 트리(decision tree)도 공유해 드리겠습니다.
01:10:48그럼 이어서 우리가 적용할 수 있는 다른 추론 최적화에는 어떤 것들이 있는지 이야기해 봐야겠네요.
01:10:58그리고 그 외에 등장한 다른 솔루션들에는 무엇이 있었는지도요.
01:11:02다시 한번 탄마이를 초대하고 싶습니다.
01:11:07탄마이가 이러한 최적화들에 대해 이야기해 줄 겁니다.
01:11:11아, 죄송합니다.
01:11:12정말 죄송합니다.
01:11:13슬라이드를 띄우는 걸 깜빡했네요.
01:11:26뭐였더라?
01:11:27좋습니다.
01:11:28됐어요.
01:11:29완벽합니다.
01:11:30어느 거지?
01:11:31추론 가속이요.
01:11:32네.
01:11:33고마워요, 하샬.
01:11:34네.
01:11:35이 모든 것들이 추론 가속(Speculative Decoding)과 관련이 있습니다.
01:11:40이 기술들은 모두... 뭐라고 해야 할까요, 똑같은 탄산음료의 다른 맛 같은 것들입니다.
01:11:46이 기법은 디코딩 가속기 범주에 속합니다.
01:11:51첫 번째로, 추론 가속뿐만 아니라 Self-speculative, Eagle, Medusa 같은 다른 변형들도 있습니다.
01:12:01개인적으로는 이 중에서도 Eagle 알고리즘이 마음에 듭니다.
01:12:05그럼 추론 가속부터 시작해 보죠.
01:12:06좋습니다.
01:12:07자.
01:12:08추론 가속이란 무엇인지부터 시작해 보죠.
01:12:09주요 문제는 트랜스포머 아키텍처에서는 이 모든 토큰이 순차적으로 하나씩 하나씩 생성된다는 점입니다.
01:12:26더 작은 모델을 사용해서, 작은 모델이 4개 또는 5개 정도의 토큰을 먼저 생성하도록 하면 어떨까요?
01:12:37그리고 이 교사 모델, 혹은 우리의 월드컵 알고리즘에 비유하자면 심판이라고 할 수 있는 모델이 있죠.
01:12:43이 심판이 토큰을 몇 개나 수락할지 결정합니다.
01:12:48그리고 이 과정이 계속해서 반복됩니다.
01:12:51우리의 가정은 이런 방식이 효과를 발휘하는 특정 도메인이 존재한다는 것입니다.
01:12:59창의성이 거의 필요 없는 코딩 같은 분야가 그 예가 될 수 있겠죠.
01:13:05각 코드나 구문이 거의 유사하니까요.
01:13:08그래서 도움이 될 수 있습니다.
01:13:10하지만 제가 직접 테스트해 본 결과, 이 추론 가속 기법은 전혀 쓸모가 없었습니다.
01:13:18하지만 교사 모델에 보조 헤드가 하나 더 있어서 베이스 모델이나 작은 모델이 하는 것과 비슷한 역할을 하는 자기 추론 가속 같은 다른 기법들도 있습니다.
01:13:35그러다가 EGLE이 나왔죠. EGLE 1, 2, 3 버전이 얼마나 있는지 모르겠지만, 토큰을 직접 생성하는 대신 작은 모델을 학습시켜 메인 모델의 레이어 중 하나에서 특성(feature)을 가져와 토큰 대신 이 특성을 생성하게 하자는 것입니다.
01:14:02따라서 EGLE은 다른 종류의 기술들에 비해 더 낫습니다.
01:14:10그리고 또 다른 하나는 MEDUSA인데, 이들은 이 모든 토큰을 병렬로 생성하자고 말합니다.
01:14:17네, 자 여기 이 슬라이드에서요.
01:14:21네.
01:14:22다음 슬라이드요.
01:14:24알겠습니다.
01:14:25좋습니다.
01:14:26네, 알겠습니다.
01:14:27좋습니다.
01:14:28이제 프리픽스 캐싱에 대해 이야기해 보겠습니다.
01:14:34사람들이 정적 프리픽스 캐싱을 사용하고 있는지 잘 모르겠습니다.
01:14:39하지만 프리픽스 캐싱의 가장 큰 문제는 때때로 우리가 타이핑을 하다가 사소한 실수를 한다는 점입니다.
01:14:47이 표준적인 정적 프리픽스 캐싱은 기본적으로 프롬프트를 받아 해싱을 수행합니다.
01:14:53그리고 다음에 사용자가 비슷한 질문을 하면 그 해시를 매칭하려고 시도하죠.
01:14:58따라서 해시가 일치하면 그 모든 K와 V를 다시 연산하는 대신 저장소에서 바로 가져옵니다.
01:15:09하지만 아시다시피 가끔 실수를 하거나 단어이나 글자 하나를 바꾸기도 합니다.
01:15:15그렇게 되면 캐시 미스율이 아주 높아지게 됩니다.
01:15:21그래서 바로 이 Radix 트리가 등장했습니다.
01:15:25에이전트의 대두와 함께 Radix 트리가 매우 인기를 얻고 있습니다.
01:15:30제 생각에는 거의 모든 사람이 에이전트를 다루고 있으며, 대부분의 연산은 테스트 시점이나 추론 과정에서 일어납니다.
01:15:38비슷한 종류의 질문과 프롬프트를 계속해서 던지는 상황 말입니다.
01:15:42예를 들어, “당신은 전문 소프트웨어 엔지니어입니다”라는 말을 200번 반복하는 식이죠.
01:15:48이러한 종류의 루프가 에이전트 시스템 내부에서 계속해서 반복됩니다.
01:15:55그렇기 때문에 유사한 내용들을 Radix 트리에 유지하거나 저장하는 것이 필수적입니다.
01:16:03Radix 트리는 분기가 없는 노드를 병합하는 방식으로 프리픽스 트리를 발전시킨 형태입니다.
01:16:17동일한 작업을 계속해서 반복하는 이러한 작업 부하에서
01:16:24Radix 트리가 큰 도움이 되며, sglang은 프리픽스 캐싱을 위해 이러한 알고리즘을 사용합니다.
01:16:35네, 그리고 또 다른 항목이 있습니다.
01:16:38바로 TensorRT-LLM입니다.
01:16:41이게 참 헷갈립니다.
01:16:42제가 처음 시작했을 때도 그냥 혼란스러웠습니다.
01:16:46TensorRT-LLM이란 도대체 무엇일까요?
01:16:49TensorRT는 표준 SDK 같은 것입니다.
01:16:55TensorRT-LLM은 그저 추론 엔진일 뿐이죠.
01:16:59vLLM이나 sglang처럼 말입니다.
01:17:01하지만 문제는 이것이 NVIDIA와 연관되어 있다는 점입니다.
01:17:05그들은 모든 레이어와 모든 문제를 최적화했습니다.
01:17:10앞서 월드컵 알고리즘에서 언급했듯이, 모든 것을 쪼개고 하드웨어 수준에서까지 최적화를 거쳤습니다.
01:17:18네, 좋습니다. 다음이요.
01:17:23네, 이번 워크숍을 위해 어떤 것이 가장 좋은지 벤치마크도 진행해 보았습니다.
01:17:33저희의 테스트 환경은 대략 이렇습니다.
01:17:36두 가지 테스트를 진행했습니다.
01:17:39첫 번째는 에이전트 테스트를 제외한 환경으로, 단순히...
01:17:44ShareGPT 데이터셋을 사용하여 vLLM과 sglang으로 질문들을 던져보는 방식이었습니다.
01:17:57좋습니다.
01:18:05네, 좋습니다.
01:18:07화면을 좀 확대하겠습니다.
01:18:12네, 좋습니다.
01:18:13이번 워크숍에서는 H100을 사용했고, 첫 번째 테스트는 다음과 같이 진행했습니다.
01:18:23ShareGPT에서 질문을 가져와 vLLM과 sglang에 입력해 본 결과, 둘 중 어느 쪽이 더 우수한지 통계적으로 유의미한 차이는 없다는 것을 발견했습니다.
01:18:34즉, 둘은 거의 유사한...
01:18:37초당 처리 요청 수, 첫 토큰 생성 시간(TTFT), 지연 시간 측면에서 모두 비슷한 성능을 보여주었습니다.
01:18:43다만 유일한 차이는 에이전트 분기(branching) 테스트에서 관찰되었습니다.
01:18:50우리가 진행한 방식은 “당신은 세계 최고의 소프트웨어 엔지니어이다”라는 전제 하에 질문을 던지는 것이었습니다.
01:18:59예를 들면 도시의 교통 체증 문제를 해결하라는 식이었죠.
01:19:04그런 다음 이를 LLM에 입력합니다.
01:19:08LLM이 결과물을 생성합니다.
01:19:10그 후 두 번째 라운드도 진행했습니다.
01:19:13LLM이 결과물을 생성하면, 두 번째 라운드에서는 특히 다음과 같은 지시를 내렸습니다.
01:19:22제안서를 검토하고 1점부터 10점까지 평점을 매겨달라고 요청했죠.
01:19:28이렇게 두 번의 턴을 거쳤고, 이 루프가 계속해서 반복됩니다.
01:19:35저희가 발견한 바로는 모든 것이 표준화된 이러한 종류의 워크플로우에서는 모든 프롬프트와 컨텍스트 엔지니어링이 중요하게 작용합니다.
01:19:47따라서 이러한 에이전트 분기를 적절히 수행한다면 SGLang이 3~4배 더 우수하다고 볼 수 있습니다.
01:19:54물론 이 역시 어떤 세팅을 쓰느냐에 따라 달라질 수 있습니다.
01:19:58직접 테스트해보시면 다른 결과를 얻으실 수도 있습니다.
01:20:02알겠습니다.
01:20:03네.
01:20:04그래서 제 생각에는...
01:20:06GitHub에 업로드했었나요?
01:20:08네.
01:20:09알겠습니다.
01:20:10네.
01:20:11PDF 파일도 드라이브에 올라와 있습니다.
01:20:15슬라이드와 같은 링크입니다.
01:20:18간단히 요약해 드리겠습니다.
01:20:22표준 API 워크로드 처리량 측면에서는 vLLM과 SGLang이 거의 동일합니다.
01:20:31따라서 만약 특별한...
01:20:33표준 워크로드를 다루고 계신다면 무조건 vLLM을 선택하세요.
01:20:36어차피 프로덕션 환경의 기본값이니까요.
01:20:38하지만 Tanmay가 말했듯이 에이전트 워크로드를 구축하려고 할 때 바로 SGLang이 진가를 발휘합니다.
01:20:50모든 이점을 제공해 준다고 볼 수 있죠.
01:20:55그렇습니다.
01:20:58기본값으로는 vLLM을 유지하시고요.
01:21:00하지만 에이전트 워크로드가 있다면 SGLang 쪽으로 전환을 고려해 보세요.
01:21:05기존 vLLM 부문에 만족하지 못하신다면 말이죠.
01:21:09알겠습니다.
01:21:10잠시만요...
01:21:15기다려 보세요.
01:21:18네.
01:21:21그리고 또...
01:21:29120B 모델에 대한 비교가 있습니다.
01:21:33GPT OSS 120B 모델 말입니다.
01:21:36이것은 PlayPy에서 준비한 벤치마크입니다.
01:21:42여기에 블로그 링크가 있습니다.
01:21:46오, 좋네요.
01:21:48좋습니다.
01:21:49네.
01:21:50그들도 비슷한 벤치마크를 진행했고 TensorRT-LLM을 포함시켰습니다.
01:21:57확실히 이러한 벤치마크들을 살펴보면 여러분의 유스케이스에 가장 적합한 것이 무엇인지 파악하는 데 도움이 될 것입니다.
01:22:05앞서 언급했듯이 TensorRT는 하드웨어 측면도 최적화하여 최고의 하드웨어 성능을 이끌어내려고 합니다.
01:22:16그리고 vLLM, SGLang, TensorRT 중에서 어떤 엔진을 쓸지 결정한 이후에 사용할 수 있는 새로운 엔진들도 등장하고 있습니다.
01:22:29대표적으로 NVIDIA Dynamo가 있죠.
01:22:43이것 역시 에이전트 세션 라우팅을 위한 것입니다.
01:22:49Hugging Face도 항상 존재합니다.
01:22:51가볍게 참고할 만하죠.
01:22:53그리고 최근 스탠퍼드에서 제안한 MSTAR 엔진도 있습니다.
01:23:00멀티모달을 위한 NVIDIA Dynamo도 있고요.
01:23:05이런 것들도 충분히 탐색해 보실 수 있습니다.
01:23:08간단히 요약하자면, 먼저 베이스라인부터 시작합니다.
01:23:15우리의 유스케이스에 적합한 모델이 무엇인지 찾으려고 노력하죠.
01:23:22DeepSeek을 선택할 수도 있습니다.
01:23:27Mistral 7B 같은 모델은 고르지 마세요.
01:23:30별로 좋지 않거든요.
01:23:32아무튼 그렇습니다.
01:23:35모델을 선택한 후 더 작은 메모리 공간에 더 큰 모델을 우겨넣고 싶을 때가 있습니다.
01:23:44GPU 비용을 아끼기 위해서죠.
01:23:47그럴 때 각종 양자화(quantization) 기법을 활용할 수 있습니다.
01:23:51그런 다음 내부적으로 적절한 서빙 엔진을 사용하여 서빙 최적화를 적용할 수 있습니다.
01:23:58이를 통해 정말로 원하는 처리량을 확보할 수 있습니다.
01:24:07그리고 집에 돌아간 후에 해볼 수 있는 일로는, 여기서 모든 자료를 다룰 수는 없으니 다양한 어텐션 메커니즘이나 여러 엔진에 대한 관련 정보를 읽어보는 것입니다.
01:24:27온라인에 공개된 다양한 벤치마크들도 읽어보시고요.
01:24:34그 다음 단계로 KV 캐시 축출 전략 등 심화 가이드나 후속 단계에 대한 내용들이 많이 있습니다.
01:24:45요즘 트렌드는 별도의 KV 캐시 엔지니어링 분야가 생겨나는 추세입니다.
01:24:50따라서 그 안에서 무슨 일이 일어나고 있는지 이해해야 합니다.
01:24:52KV 축출, 캐시 압축, 하이브리드 메모리 같은 것들 말이죠.
01:24:57이와 관련해서 정말 많은 솔루션들이 나오고 있습니다.
01:25:01항상 기초나 근본 원리에 집중하려고 노력하세요.
01:25:08어떤 솔루션이 어떤 문제를 해결하는지, 그리고 여러분의 유스케이스에서 실제로 그 문제를 해결할 필요가 있는지 확인해 보세요.
01:25:17그리고 분산 LLM 추론이라는 완전히 다른 핵심 주제도 존재합니다.
01:25:26내부 구조를 모두 살펴보고 실습까지 하려면 아마 두 시간짜리 워크숍이 필요할 것입니다.
01:25:40네, 이건 우리가 AI 엔지니어 뉴욕 세션에서 제안하려고 하는 내용인데, LLM 추론의 고급 섹션을 더 깊게 파고드는 것입니다.
01:25:51이번 워크숍은 초·중급자를 대상으로 한 성격이 더 강했습니다.
01:25:55따라서 이 양식을 통해 피드백과 함께 관심도 받을 수 있습니다.
01:26:02특정 섹션에 개선이 필요하다고 생각되시면 꼭 피드백을 남겨주세요.
01:26:09그리고 뉴욕 페어에서 이 워크숍을 보고 싶으시다면, 편하게 참여 의사를 등록해 주시기 바랍니다.
01:26:22네?
01:26:24아, 이게 어떻게 가능하죠?
01:26:27이런.
01:26:32잠깐 확인해 볼게요.
01:26:37좋습니다.
01:26:38네?
01:26:39네.
01:26:40URL은 잘 작동하죠?
01:26:41네.
01:26:42QR 코드가 아니라요?
01:26:43알겠습니다.
01:26:44제가 두 개를 연결하는 걸 깜빡했나 보네요.
01:26:45알겠습니다.
01:26:46좋습니다.
01:26:46네.
01:26:47그럼 그걸 주실 수 있다면요.
01:26:49알겠습니다.
01:26:50좋습니다.
01:26:51네.
01:26:52그럼 그걸 주실 수 있다면요.
01:26:53알겠습니다.
01:26:54네.
01:26:55알겠습니다.
01:26:56좋습니다.
01:26:57네.
01:26:58그럼 그걸 주실 수 있다면요.
01:26:59제가 좀...
01:27:00알겠습니다.
01:27:00알겠습니다.
01:27:01좋습니다.
01:27:02네.
01:27:02그럼 그걸 주실 수 있다면요.
01:27:03제가 좀...
01:27:04알겠습니다.
01:27:05그럼 되겠네요.
01:27:06음, 그리고 네, 이제 이 워크숍을 마무리하면 좋을 것 같습니다.
01:27:13그리고 여러분 중 많은 분이 질문이 있으실 거예요.
01:27:14그래서 그런 것들은 오프라인으로 다루면 됩니다.
01:27:15어, 만나서 그런 질문들에 대해 이야기 나눌 수 있습니다.
01:27:16네.
01:27:17물론입니다.
01:27:18물론이죠.
01:27:19어, 모두 감사드립니다.
01:27:20참여해 주셔서 감사해요.
01:27:21어, 정말...
01:27:22어, 모두 감사드립니다.
01:27:23어, 모두 감사드립니다.
01:27:24참여해 주셔서 감사해요.
01:27:25어, 모두 감사드립니다.
01:27:26참여해 주셔서 감사해요.
01:27:27어, 정말...
01:27:28아, 알겠습니다.
01:27:29어, 알겠습니다.
01:27:30그럼 되겠네요.
01:27:31어, 그리고 네, 이제 이 워크숍을 마무리하면 좋을 것 같습니다.
01:27:33어, 그리고 네, 이제 이 워크숍을 마무리하면 좋을 것 같습니다.
01:27:36그리고 여러분 중 많은 분이 질문이 있으실 거예요.
01:27:39그래서 그런 것들은 오프라인으로 다루면 됩니다.
01:27:41어, 만나서, 어, 그 질문들에 대해, 어, 이야기 나눌 수 있습니다.
01:27:42네, 물론입니다.
01:27:43어, 모두 감사드립니다.
01:27:44어, 정말 의미 있었고 여러분 모두 이렇게 참석해 주셔서...
01:27:49어, 정말 감사드립니다.
01:27:50네, 감사합니다.

핵심 요약

LLM 추론 과정에서 발생하는 메모리 부족과 지연 시간 문제를 해결하기 위해 양자화, 그룹드 쿼리 어텐션, 페이드 어텐션, 그리고 연속 배치 등의 최적화 기술을 적용해야 한다.

하이라이트

  • LLM 추론 시장은 약 230억 달러 규모이며, 구글 검색 쿼리를 LLM으로 처리하려면 360억 달러의 자금 유출과 쿼리당 0.5센트 미만의 비용 달성이 필요하다.

  • 미스트랄 7B 모델을 기준으로 토큰당 KV 크기는 대략 131바이트이며, 4K 컨텍스트 사용 시 약 0.5GB, 16K 컨텍스트 사용 시 약 2.1GB의 메모리를 소비한다.

  • 프리필 단계는 방대한 행렬 연산과 키-값 벡터 생성으로 인해 연산 집약적이며 첫 토큰 생성 시간(TTFT)을 결정한다.

  • 디코드 단계는 고대역폭 메모리(HBM)와 공유 메모리 간의 데이터 전송 속도 제한을 받는 메모리 바운드 연산이다.

  • vLLM은 페이징 기법, 연속 배치, 프리픽스 캐싱을 기본 제공하여 순차적 방식 대비 처리량을 최대 15배까지 향상시킨다.

  • 에이전트 워크로드 환경에서는 SGLang이 표준 프리픽스 캐싱과 Radix 트리를 활용하여 vLLM 대비 3배에서 4배 더 우수한 성능을 발휘한다.

타임라인

LLM 추론의 고충점과 비용 문제

  • LLM 추론 시장의 규모는 현재 약 230억 달러에 달한다.
  • 검색 사업을 유지하려면 쿼리당 비용이 0.5센트 미만이어야 한다.
  • 훈련 비용과 달리 추론 비용은 사용자 유입과 토큰 증가에 따라 선형적으로 증가하는 반복적 운영 비용이다.

오디블의 하샬 진과 독립 AI 연구원 탄마이 샤가 진행하는 워크숍의 도입부이다. AI 사용이 급증함에 따라 하드웨어 한정과 높은 연산 비용으로 인해 추론 비용이 치솟고 있음을 지적한다. 세미애널리시스와 비즈니스 인사이더의 분석을 인용하여 토큰 사용량 감사와 예산 책정의 필요성을 강조한다. 또한 Mistral 7B 모델을 활용한 실제 데모를 통해 컨텍스트 길이가 길어질수록 메모리와 첫 토큰 생성 시간이 급격히 증가하는 고충점을 시각적으로 증명한다.

추론 파이프라인의 기초와 연산 구조

  • 트랜스포머 레이어 내부 연산의 95% 이상이 어텐션 레이어에서 소모된다.
  • 미스트랄 7B 기준 토큰당 키-값(KV) 크기는 약 131바이트이며 4K 컨텍스트에서 0.5GB를 차지한다.
  • 입력 토큰을 처리하는 프리필 단계는 연산 집약적이며, 단일 토큰을 순차 생성하는 디코드 단계는 메모리 바운드 연산이다.

추론 파이프라인의 내부 작동 방식을 제1원칙부터 분석한다. 어텐션 메커니즘은 모든 이전 토큰에 대한 키, 쿼리, 밸류 벡터를 생성하므로 입력 크기가 커질수록 메모리 점유율이 폭발적으로 증가한다. GPU의 고대역폭 메모리(HBM)와 공유 메모리 간의 데이터 전송 메커니즘을 설명하며, 프리필 단계가 첫 토큰 생성 시간(TTFT)을 좌우하고 디코드 단계가 HBM 대역폭 한계에 묶이는 이유를 수학적 루프라인 플롯으로 규명한다.

모델 최적화 기법

  • 모델의 메모리 점유율을 줄이기 위해 FP16에서 INT8, INT4 등으로 사후 학습 양자화를 수행한다.
  • 멀티 헤드 어텐션의 연산 과부하를 줄이기 위해 그룹드 쿼리 어텐션(GQA)과 멀티 헤드 레이턴트 어텐션(MLA)을 도입한다.
  • 플래시 어텐션은 전체 행렬을 한 번에 곱하는 대신 작은 타일 단위로 나누어 SRAM에서 연산한다.

탄마이 샤가 모델 최적화 세션을 이어간다. H100 같은 단일 GPU의 한정된 VRAM에 거대한 모델 가중치를 억지로 올리기 위한 양자화 전략을 다룬다. 행렬 연산 속도를 높이기 위해 쿼리, 키, 밸류 블록을 쪼개거나 병합하는 어텐션 변형 모델들을 비교한다. 멀티 헤드 어텐션, 그룹드 쿼리 어텐션, 멀티 쿼리 어텐션, 그리고 딥시크의 멀티 헤드 레이턴트 어텐션 간의 품질과 처리량 트레이드오프를 상세히 분석한다.

서빙 엔진 최적화와 벤치마크

  • 페이지드 어텐션은 운영체제의 가상 메모리 페이징 기법에서 영감을 받아 KV 캐시의 메모리 단편화를 방지한다.
  • 연속 배치는 GPU가 유휴 상태로 노는 시간을 없애고 처리량을 극대화한다.
  • 표준 API 워크로드에서는 vLLM과 SGLang의 성능이 비슷하지만, 에이전트 분기 워크로드에서는 SGLang이 3배에서 4배 더 우수하다.

실제 프로덕션 환경에서 추론 솔루션을 서빙하기 위한 최적화 엔진과 기법들을 다룬다. KV 캐시를 효율적으로 관리하는 페이지드 어텐션과 여러 요청을 동적으로 묶는 연속 배치의 작동 원리를 설명한다. vLLM, SGLang, TensorRT-LLM의 벤치마크 결과를 비교하여 각 엔진의 특장점을 명시한다. 특히 에이전트 세션 라우팅과 반복적인 프롬프트 캐싱이 필요한 환경에서는 Radix 트리를 사용하는 SGLang이 최적의 선택임을 입증한다.

커뮤니티 글

아직 글이 없습니다. 이 영상에 대한 첫 번째 글을 작성해 보세요!

이 영상에 대해 글쓰기