GPU 자원 80% 유휴 상태를 해결하는 MPS의 구조

단일 ASR(Automatic Speech Recognition, 자동 음성 인식) 추론 요청은 전체 GPU 연산 능력의 15~20%만을 점유하며, 이로 인해 80%의 하드웨어 자원이 유휴 상태로 방치되는 비효율이 발생한다. 이러한 자원 낭비는 기업이 동일한 처리량을 확보하기 위해 더 많은 인스턴스를 운영하게 만드는 직접적인 원인이 된다. 실제로 기존의 시간 분할(Time-slicing) 방식에서는 16대의 GPU 인스턴스가 필요했던 작업량이, NVIDIA CUDA MPS(Multi-Process Service, 다중 프로세스 서비스)를 적용함으로써 4대의 인스턴스만으로 처리가 가능해져 전체 인프라 요구량을 75% 절감하는 결과로 이어졌다.

기본적인 CUDA 시간 분할 방식은 여러 프로세스가 GPU에 접근할 때 순차적인 실행을 강제한다. 프로세스들은 차례를 기다리며 GPU를 독점적으로 점유하는데, 이 과정에서 프로세스 간 전환(Context switching)에 따른 오버헤드가 추가로 발생한다. 결과적으로 특정 시점에 GPU는 오직 하나의 프로세스만을 처리하게 되며, 나머지 연산 자원은 대기 상태로 머물게 된다. 이는 Parakeet TDT 0.6B V2 모델과 같이 상대적으로 가벼운 모델을 실행할 때 GPU가 가진 142개의 SM(Streaming Multiprocessors, 스트리밍 멀티프로세서)을 충분히 활용하지 못하게 만드는 병목 구간이 된다.

NVIDIA CUDA MPS는 이러한 시간 분할의 한계를 극복하기 위해 설계된 바이너리 호환 가능한 CUDA API 구현체다. MPS는 여러 프로세스의 작업을 단일 GPU 컨텍스트로 통합하여 하드웨어 자원을 공유하도록 지원한다. 이를 통해 개별 프로세스가 GPU를 독점하지 않고도 병렬로 연산을 수행할 수 있는 환경이 조성된다. 결과적으로 GPU는 여러 요청을 동시에 처리하며 SM 점유율을 극대화할 수 있게 된다. MPS를 도입하면 GPU를 여러 개의 동시 실행 인스턴스로 분할하여 운영할 수 있으며, 이는 고정된 하드웨어 자원 내에서 추론 처리량(RPS, Requests Per Second)을 획기적으로 높이는 기반이 된다.

Triton Inference Server와 MPS의 결합 및 배치 전략

단일 GPU 환경에서 초당 62건의 요청(RPS)을 처리하는 기존 방식은 평균 650ms, p99 1,000ms 미만의 지연 시간 요구사항(SLA)을 충족하기 위해 총 16대의 GPU를 필요로 한다. 이러한 자원 활용 격차를 해소하기 위해 전사 인스턴스(Transcription)는 25%의 SM(Streaming Multiprocessor, GPU 내 연산 핵심 단위)을 할당하여 4개의 동시 프로세스를 운영하고, 화자 분리 인스턴스(Diarization)는 12%의 SM을 할당하여 8개의 동시 프로세스를 실행하는 방식으로 최적화했다. 각 전사 인스턴스는 48GB VRAM 중 약 2.5GB를, 화자 분리 인스턴스는 약 1.8GB를 점유한다.

이러한 물리적 분할을 효율적으로 제어하기 위해 NVIDIA Triton Inference Server(모델 추론을 위한 오픈소스 서버)의 스케줄링 기능을 MPS(Multi-Process Service, 다중 프로세스 간 GPU 자원을 공유하는 NVIDIA의 기술) 파티션에 1:1로 매핑했다. 이를 통해 Triton의 배치 스케줄러가 각 MPS 파티션으로 요청을 직접 분배하며, 추론 파이프라인은 전사 작업에 동적 배치(Dynamic Batching)를, 화자 분리 작업에는 시퀀스 배치(Sequence Batching) 전략을 적용한다. 동적 배치는 [4, 8, 16]의 배치 크기를 선호하며 최대 50,000마이크로초의 대기 시간을 허용하여 처리량을 최적화한다.

구현을 위한 컨테이너 실행 순서는 다음과 같다. 먼저 CUDA MPS 데몬을 Triton 컨테이너 내부에서 구동한 뒤, auto_config.py를 실행하여 Triton 인스턴스 개수와 SM 할당 비율을 설정한다. 마지막으로 tritonserver를 실행하여 추론 엔진을 가동한다.

bash
(1) start the CUDA MPS daemon
(2) run auto_config.py to set the Triton instance count and SM percentage
(3) launch tritonserver

이와 같은 구조는 Triton의 요청 스케줄러와 GPU 분할 레이어를 통합하여 하드웨어 자원의 유휴 구간을 최소화한다. 전체 빌드 및 실행에 관한 상세 지침은 저장소(https://github.com/aws-samples/amazon-ec2-asr-inference-optimization)를 참조할 수 있다.

ONNX Runtime과 TensorRT를 활용한 연산 최적화

ASR(자동 음성 인식) 추론 파이프라인의 연산 비용은 모델의 각 구성 요소가 하드웨어 자원을 얼마나 효율적으로 점유하느냐에 따라 결정된다. 본 최적화는 연산 집약적인 Conformer 인코더에 ONNX Runtime(오픈 신경망 교환 모델을 실행하는 고성능 추론 엔진)을 적용하고, NVIDIA TensorRT(NVIDIA GPU 하드웨어에 최적화된 추론 가속기)를 실행 제공자로 활용하여 처리 시간을 단축한다. 이 방식은 모델의 그래프 노드를 하드웨어에 특화된 커널로 변환하여 연산 효율을 높이는 구조다.

TensorRT 실행 제공자는 모델의 연산 그래프를 분석하여 커널 융합(Kernel Fusion, 다수의 연산 단계를 하나로 합쳐 메모리 접근을 줄이는 기법)을 수행하고, FP16(16비트 부동소수점 정밀도) 정밀도 보정을 적용한다. 이를 통해 Conformer 인코더의 24개 레이어와 1024개 히든 차원에서 발생하는 연산 부하를 하드웨어 수준에서 최적화한다. 이러한 최적화는 NVIDIA L40S GPU 환경에서 수행되었으며, 다른 GPU 아키텍처에서의 성능 수치는 확인되지 않았다.

전체 파이프라인은 하이브리드 방식을 채택하여 인코더와 디코더의 특성에 맞는 실행 환경을 분리한다. RNN-T(Recurrent Neural Network Transducer, 음성 인식 및 토큰 생성을 담당하는 모델 구조) 디코더는 정적인 TensorRT 엔진보다 유연한 대응이 필요한 가변 길이 토큰 생성 작업을 처리해야 한다. 따라서 디코더는 PyTorch CUDA 네이티브 환경에서 실행하며, CUDA 그래프 캐싱(반복적인 연산 호출을 미리 기록하여 오버헤드를 줄이는 기술)을 통해 토큰 생성 효율을 확보한다.

이러한 구조적 접근은 정적인 연산은 TensorRT로 가속하고, 동적인 생성 과정은 CUDA 그래프 캐싱으로 처리함으로써 GPU 자원 활용도를 극대화한다. 결과적으로 고정된 연산 패턴을 가진 인코더와 가변적인 디코더 사이의 처리 병목 현상을 최소화한다.

Amazon EC2 g6e 및 g7e 인스턴스 배포 아키텍처

Amazon EC2 g6e.4xlarge 및 g7e.4xlarge 인스턴스에서 NVIDIA L40S GPU의 48GB VRAM을 최대로 활용하기 위해 FastAPI 게이트웨이와 Triton 추론 서버, 그리고 MPS 데몬으로 구성된 3계층 파이프라인을 구축한다. 이 아키텍처는 단일 GPU 환경에서 다수의 추론 요청을 효율적으로 처리하도록 설계되었으며, 모든 구성 요소는 Docker Compose를 통해 컨테이너화되어 운영된다. 하드웨어 리소스의 물리적 제약을 극복하고 연산 효율을 높이는 것이 이 배포 방식의 핵심이다.

FastAPI 게이트웨이는 외부 클라이언트로부터 수신된 오디오 데이터를 처리하는 첫 번째 관문이다. 이 계층은 OpenAI Whisper 호환 REST API를 제공하며, 업로드된 오디오 파일을 16kHz 샘플링 레이트의 모노 채널 float32 텐서 데이터로 변환한다. 변환된 데이터는 gRPC(Google Remote Procedure Call, 분산 시스템 간 효율적인 통신을 위한 고성능 프레임워크)를 통해 Triton 추론 서버로 전달된다. 게이트웨이는 4개의 uvicorn 워커를 통해 8002번 포트에서 요청을 수신하며, 데이터 전처리 과정을 담당하여 추론 엔진의 부하를 줄인다.

Triton 추론 서버는 전달받은 텐서 데이터를 받아 실제 모델 추론을 수행하는 핵심 엔진이다. 서버는 MPS(Multi-Process Service, 여러 프로세스가 단일 GPU 컨텍스트를 공유하여 동시성을 높이는 NVIDIA 기술)를 통해 분할된 모델 인스턴스로 요청을 분산한다. 이 과정에서 각 모델 인스턴스는 GPU 자원을 할당받아 독립적으로 연산을 수행하며, 결과값은 다시 게이트웨이를 거쳐 사용자에게 반환된다. 이러한 3계층 구조는 인프라 요구 사항을 기존 대비 75%까지 절감하며, GPU당 초당 92.1개의 요청을 처리하면서도 1초 미만의 지연 시간을 유지한다.

해당 아키텍처의 상세 구현과 설정 파일은 공식 저장소에서 확인할 수 있다. 배포 환경 구성 및 실행에 필요한 전체 코드는 다음 링크에서 제공한다.

https://github.com/aws-samples/amazon-ec2-asr-inference-optimization

이러한 배포 방식은 고성능 추론이 필요한 환경에서 GPU 가동률을 극대화하는 표준적인 인프라 구성 전략을 제시한다.

실무 환경 도입을 위한 배포 및 설정 가이드

NVIDIA L40S GPU 환경에서 CUDA MPS(Multi-Process Service, 다중 프로세스 간 GPU 자원을 효율적으로 공유하는 기술)를 적용할 때 인스턴스 간 SM(Streaming Multiprocessor, GPU 내 연산 처리 단위) 할당 비율을 수동으로 조정하는 것은 운영 복잡도를 높이는 주된 요인이다. 실제 운영 환경에서는 제공된 오픈소스 저장소(https://github.com/owner/repo)를 활용해 컨테이너 기반으로 MPS 데몬과 Triton(NVIDIA의 추론 서버)을 자동 배포하는 방식을 권장한다. 저장소 내 포함된 Docker Compose(여러 컨테이너를 정의하고 실행하는 도구) 설정은 GPU 추론 계층과 CPU 게이트웨이 계층을 분리하여 독립적인 확장을 지원한다.

배포는 저장소를 복제한 뒤 다음 세 단계 명령어를 실행하여 수행한다. 빌드 과정에서 컨테이너 이미지는 MPS 데몬의 실행, 모델 로드, 상태 모니터링을 자동으로 처리하도록 구성되어 있다.

bash
git clone https://github.com/owner/repo
docker compose build
docker compose up

런타임 동작은 환경 변수를 통해 제어하며, 주요 항목으로 MPS_INSTANCE_COUNT, GATEWAY_WORKERS, TRITON_URL, CUDA_VISIBLE_DEVICES가 있다. 특히 MPS_INSTANCE_COUNT는 Triton 인스턴스 그룹 수와 각 인스턴스당 SM 백분율을 동시에 설정하는 핵심 변수다. 저장소에 포함된 auto_config.py 스크립트는 이 값을 기반으로 GPU 자원 할당을 자동 계산하여 인프라 구성의 일관성을 유지한다. 서비스의 준비 상태는 /health 엔드포인트를 통해 확인할 수 있으며, 일반적으로 컨테이너 시작 후 90에서 120초 이내에 200 응답을 반환한다.

이러한 자동화된 배포 구조는 수동 설정 시 발생할 수 있는 자원 할당 오류를 방지하고, 동일한 컨테이너 이미지를 다양한 GPU 환경에서 재사용할 수 있게 한다. 인프라 운영자는 환경 변수 조정만으로 Triton의 동적 배치 전략과 MPS 파티션을 1대1로 매핑하여 GPU 점유율을 최적화할 수 있다. 최종적으로 서비스 안정성을 확보하기 위해서는 배포 후 /health 엔드포인트의 응답을 통해 서비스 준비 완료 여부를 확인하는 단계를 반드시 포함해야 한다.