5 분 소요

Prefill과 Decode 구조를 이해하면 추론 엔지니어링에서 사용하는 주요 최적화 기술을 훨씬 쉽게 정리할 수 있다. 각 기술은 특정 단계를 가속하거나, 서로 다른 이유로 두 단계를 모두 개선하거나, 또는 Prefill과 Decode 구조 자체를 중심으로 시스템을 재구성한다. 이제 대표적인 여섯 가지 최적화 기술을 자세히 살펴본다

1. 배칭

배칭은 하나의 GPU 처리량(output)을 확장하는 가장 기본적인 방법이다. 추론 엔진은 여러 사용자의 요청을 하나로 묶고, 토큰 단위로 인터리빙(interleaving)하여 하나의 GPU가 동시에 여러 사용자를 처리할 수 있도록 한다.

이를 통해 GPU의 계산 자원을 최대한 활용할 수 있다. 요청 사이에서 GPU가 유휴 상태로 머무르는 시간을 줄이고, 전체 처리량을 크게 증가시킬 수 있다.

하지만 배칭은 사용자별 지연 시간을 증가시키는 비용을 가진다. 배칭을 사용하지 않는 시스템에서는 하나의 사용자가 가능한 가장 빠른 응답 시간을 얻는다. 반면 대규모 배칭 환경에서는 GPU가 동시에 다른 사용자의 요청도 처리하기 때문에 특정 사용자의 요청은 더 오래 기다릴 수 있다.

이러한 지연 시간과 처리량 사이의 균형(latency-throughput trade-off)은 다른 모든 추론 최적화 기술이 해결해야 하는 핵심 문제이다. 제품의 특성에 따라 최적 지점은 달라진다. 예를 들어, 소비자용 대화형 AI 서비스는 낮은 지연 시간을 우선시한다. 반면 대량 데이터 처리 파이프라인은 높은 처리량을 우선시한다.

inference-02

2. 접두사 캐싱(Prefix Caching)

접두사 캐싱()Prefix Caching)은 여러 요청에서 반복되는 입력 부분을 재사용하여 Prefill 단계를 가속하는 기술이다. 두 개의 프롬프트가 동일한 시작 부분(prefix)을 공유하는 경우를 생각해 볼 수 있다.

예를 들어, 수천 개의 요청에서 동일하게 사용되는 긴 시스템 프롬프트가 있다면, 추론 엔진은 해당 Prefix를 한 번만 계산하고 이후 요청에서는 캐시에서 결과를 읽는다. 이러한 이유로 API 제공 업체들은 캐시된 입력 토큰에 대해 더 낮은 비용을 부과한다.

하지만 접두사 캐싱()Prefix Caching)에는 제한 사항이 있다. 캐시는 두 입력 시퀀스가 일치하는 첫 번째 구간부터 처음으로 다른 토큰이 나타나는 지점까지만 효과가 있다. 만약 두 프롬프트의 첫 번째 토큰부터 다르다면, 이후 내용이 동일하더라도 접두사 캐싱으로 얻는 이점은 없다.

따라서 프롬프트 구조는 비용과 지연 시간에 직접적인 영향을 준다. 공통적으로 사용하는 내용을 프롬프트 앞부분에 배치하고, 변경되는 사용자 입력을 뒤쪽에 배치하면 캐시 활용률을 높일 수 있다.

inference-03

3. 양자화

양자화(quantization)는 Prefill과 Decode 두 단계 모두를 개선할 수 있지만, 각각 다른 방식으로 동작한다. 기본적인 방식은 모델 가중치를 더 낮은 정밀도의 숫자 형식으로 저장하는 것이다. 대부분의 최신 AI 모델은 학습 과정에서 16비트 부동소수점(16-bit floating point)을 사용한다.

양자화는 이러한 값을 8비트 또는 4비트 표현 방식으로 압축한다. 그 결과 모델 가중치 크기가 감소하고, 메모리 사용량이 줄어들며, 데이터를 이동시키는 양도 감소한다.

Prefill 단계에서는 낮은 정밀도의 연산이 최신 GPU 내부의 특수 연산 장치에서 더 빠르게 실행되기 때문에 성능이 향상된다. Decode 단계에서는 메모리 대역폭에 대한 부담이 줄어들어 각 순전파마다 필요한 가중치를 더 빠르게 읽을 수 있다.

일반적으로 정밀도를 한 단계 낮추면 약 30%에서 50% 수준의 성능 향상을 얻을 수 있다. 하지만 실제 향상 폭은 모델 구조와 적용한 양자화 방식에 따라 달라진다.

양자화의 가장 큰 비용은 모델 품질이 저하될 가능성이다. 모델 내부의 모든 구성 요소가 동일한 수준으로 양자화를 견디는 것은 아니다. 일반적으로 선형 가중치는 양자화에 비교적 강하다. 반면 활성화 값(activation)은 더 민감하며, KV 캐시는 더욱 민감하다. 그리고 어텐션 계층(attention layer)은 가장 높은 민감도를 가진다.

그 이유는 어텐션 계층에서 발생하는 작은 정밀도 오류가 토큰 생성 과정 전체에 걸쳐 누적되기 때문이다. 각 토큰의 계산 결과는 이전 토큰의 결과에 영향을 받는다. 따라서 초기 단계에서 발생한 작은 오차도 긴 응답을 생성하는 과정에서는 점점 확대되어 최종 품질 저하로 이어질 수 있다.

이러한 이유 때문에 대부분의 운영 환경에서는 어텐션 계층을 높은 정밀도(full precision) 상태로 유지한다. 양자화 엔지니어링의 핵심 작업은 모델의 어떤 부분을 압축할 것인지, 그리고 어느 수준까지 압축할 것인지를 결정하는 것이다.

inference-04

4. 추측 디코딩

추측 디코딩(speculative decoding)은 특정한 비대칭성을 활용하여 Decode 과정을 가속하는 기술이다. 새로운 토큰을 처음부터 생성하는 작업은 비용이 높다. 하지만 특정 후보 토큰(candidate token)이 메인 모델이 생성할 결과와 일치하는지 확인하는 작업은 훨씬 저렴하다. 이 개념은 스도쿠에 비유할 수 있다. 퍼즐을 처음부터 해결하는 것은 많은 시간이 필요하지만, 이미 완성된 퍼즐의 정답 여부를 확인하는 것은 빠르게 수행할 수 있다.

추측 디코딩에서는 작은 초안 모델이 다음에 생성될 여러 개의 토큰을 먼저 예측한다. 그 다음 주요 모델(main model)은 하나의 순전파 과정에서 이 후보 토큰들을 한꺼번에 검증한다. 주요 모델의 예측과 일치하는 토큰은 그대로 승인하고, 일치하지 않는 토큰은 거부한다. 그 결과 기존 방식에서는 주요 모델이 한 번의 순전파마다 하나의 토큰만 생성하던 것을, 여러 개의 토큰을 동시에 생성하는 효과를 얻을 수 있다.

추측 디코딩은 TPS(Tokens Per Second)를 향상시키지만 TTFT(Time To First Token)는 변경하지 않는다. Prefill 과정은 기존 방식과 동일하게 수행되기 때문이다. 또한 이 기술은 작은 배치 크기에서 가장 효과적이다. 이 경우 GPU에 검증 작업을 수행할 여유 연산 자원(spare compute capacity)이 남아 있기 때문이다.

반대로 큰 배치 크기에서는 많은 요청이 동시에 처리되고 GPU가 이미 포화 상태(saturated state)에 도달한다. 이 상황에서는 모든 GPU 연산 주기가 주요 작업 처리에 필요하기 때문에 추측 디코딩 기능은 동적으로 비활성화된다.

inference-05

5. 병렬 처리

병렬 처리(parallelism) 기술은 하나의 GPU로 처리하기 어려운 대규모 모델을 멀티 GPU에서 실행할 수 있도록 한다. 이러한 상황은 두 가지 이유로 발생한다.

첫째, 모델 크기가 너무 커서 하나의 GPU 메모리에 저장할 수 없는 경우이다. 둘째, 하나의 GPU에서 처리하는 지연 시간이 너무 높은 경우이다.

오픈 모델 생태계에서는 두 가지 주요 병렬 처리 방식이 널리 사용된다.

5-1. 텐서 병렬 처리

텐서 병렬 처리(Tensor Parallelism)는 모델의 각 계층을 멀티 GPU에 나누어 실행한다. 각 GPU는 모든 계층의 일부 조각을 저장하고, 하나의 순전파 과정에서 GPU들이 작업을 분담한다. 이 방식은 GPU 간 높은 대역폭 연결을 필요로 한다.

예를 들어, NVIDIA NVLink와 같은 고속 인터커넥트가 필요하다. 각 계층이 처리될 때마다 멀티 GPU에서 계산된 결과를 다시 결합해야 하기 때문이다. 텐서 병렬 처리는 매우 큰 밀집 모델(dense model)을 서비스하는 환경에서 기본적으로 사용되는 방식이다. 계층별 계산을 멀티 GPU가 나누어 수행함으로써 얻는 성능 향상이 높은 통신 비용을 상쇄하기 때문이다.

5-2 엑스퍼트 병렬 처리

엑스퍼트 병렬 처리(Expert Parallelism)는 혼합 전문가 모델(Mixture-of-Experts, MoE)에 특화된 방식이다. MoE 모델에서는 각 토큰마다 전체 모델 파라미터가 모두 활성화되지 않는다.대신 일부 엑스퍼트(expert)만 선택적으로 활성화된다.

참고로 엑스퍼트란 특정 유형의 입력이나 패턴을 전문적으로 처리하도록 학습된 독립적인 신경망 블록(neural network block)을 말한다. 엑스퍼트 병렬 처리에서는 서로 다른 엑스퍼트를 멀티 GPU에 분산 배치한다. 그리고 각 토큰은 필요한 엑스퍼트가 위치한 GPU로 전달된다. 이 방식은 전문가가 독립적으로 동작하기 때문에 텐서 병렬 처리보다 통신 부담이 낮다.

따라서 GPU 간 대역폭이 상대적으로 제한적인 멀티 노드(multi-node) 환경에서 적합하다. 실제 운영 환경에서는 두 방식을 함께 사용하는 경우가 많다. 일반적으로 하나의 노드 내부에서는 텐서 병렬 처리를 사용하고, 멀티 노드 사이에서는 엑스퍼트 병렬 처리를 적용한다.

inference-06

6. 분리(Disaggregation)

분리(disaggregation)은 Prefill과 Decode 분리 구조를 시스템 아키텍처 수준에서 직접 적용하는 방식이다. 핵심 아이디어는 Prefill 작업은 하나의 GPU 그룹에서 실행하고, Decode 작업은 다른 GPU 그룹에서 실행하는 것이다.

두 그룹 사이에서는 KV 캐시를 네트워크를 통해 전달한다. 각 GPU 그룹은 자신의 병목 특성에 최적화된 하드웨어를 사용할 수 있으며, 각각의 트래픽 패턴에 따라 독립적으로 확장할 수 있다.

디스어그리게이션 구조의 처리 흐름은 세 단계로 구성된다.

  • 1단계: Prefill 엔진이 입력 시퀀스를 처리한다. 이 과정에서 첫 번째 토큰과 KV 캐시를 생성한다.
  • 2단계: 생성된 KV 캐시는 고속 인터커넥트(fast interconnect)를 통해 Decode 엔진으로 전달된다. Decode 엔진은 이후 생성되는 모든 토큰을 처리한다.
  • 3단계: 조건부 분리(conditional disaggregation) 환경에서는 짧은 요청이나 이미 캐시된 요청은 KV 캐시 전달 과정을 생략한다. 이러한 요청은 바로 Decode 엔진에서 처리되며, 긴 프롬프트와 짧은 프롬프트가 혼합된 실제 서비스 환경에서 더 높은 효율을 제공한다.

분리는 지금까지 설명한 기술 중 가장 아키텍처 중심적인 접근 방식이다. 이 방식은 Prefill과 Decode를 서로 다른 서비스로 분리하고, 각각 별도의 운영 관리 요소를 갖도록 한다. 이를 통해 운영자는 각 단계의 확장 정책을 독립적으로 조정할 수 있다. 대규모 추론 서비스를 운영하는 기업에서는 워크로드 특성이 충분히 분석된 이후 분리를 필수적인 단계로 고려하는 경우가 많다.

inference-07

댓글남기기