이 글은 TensorRT-LLM으로 LLM 추론 성능을 벤치마킹하고 최적화하는 방법을 소개하는 시리즈의 세 번째 편입니다.이 시리즈에서는 개발자가 TensorRT-LLM을 활용해 효율적인 LLM 추론 환경을 구축하는 방법을 단계별로 안내하는데요. 기본적인 벤치마크 지표와 파라미터 개념은 LLM Inference Benchmarking: Fundamental Concepts에서, GenAI-Perf와 NVIDIA NIM 활용 팁은 LLM Inference Benchmarking Guide: NVIDIA GenAI-Perf and NIM에서 확인할 수 있습니다.
거대 언어 모델(LLM) 프레임워크를 배포·통합·벤치마크할 때는 반드시 추론 성능을 고려해야 합니다. 애플리케이션에 중요한 성능 지표를 달성하려면, 선택한 프레임워크와 그 기능들을 적절히 튜닝하는 것이 중요합니다.
TensorRT-LLM은 NVIDIA의 오픈소스 AI 추론 엔진으로, 네이티브 벤치마킹 및 서빙 툴을 활용해 모델을 배포할 수 있으며, 다양한 기능을 세밀하게 조정할 수 있습니다. 이번 글에서는 trtllm-bench
로 모델을 튜닝하고, 그 결과를 활용해 trtllm-serve
로 배포하는 실전 가이드를 소개합니다.
trtllm-bench로 벤치마크하기
trtllm-bench
는 전체 추론 배포의 오버헤드 없이 모델을 직접 벤치마크할 수 있는 Python 기반 유틸리티입니다. 빠르게 성능 인사이트를 얻을 수 있도록 내부적으로 최적 설정을 적용해 엔진을 구성합니다.
GPU 환경 설정
벤치마크는 올바르게 구성된 GPU 환경에서 시작됩니다. GPU를 기본 설정으로 복원하려면 다음을 실행합니다.
sudo nvidia-smi -rgc
sudo nvidia-smi -rmc
GPU 최대 전력 사용량을 확인하려면 아래와 같이 설정합니다:
nvidia-smi -q -d POWER
특정 전력 제한(또는 최대값)을 설정하려면 아래와 같이 설정합니다:
nvidia-smi -i <gpu_id> -pl <wattage>
자세한 내용은 trtllm-bench 문서를 참고하세요.
데이터셋 준비
prepare_dataset
로 합성 데이터셋을 만들거나, 문서에 지정된 형식을 따라 직접 데이터셋을 생성할 수 있습니다. 사용자 정의 데이터셋의 경우, 각 줄에 페이로드를 구성한 JSON Lines(jsonl) 파일 형식을 사용할 수 있습니다. 단일 데이터 항목 예시는 아래와 같습니다.
{"task_id": 1, "prompt": "Generate infinitely: This is the song that never ends, it goes on and on", "output_tokens": 128}
이번 글에서는 ISL/OSL이 128/128인 합성 데이터셋을 기반으로 한 예시 출력을 제공합니다.
벤치마크 실행
trtllm-bench
로 벤치마크를 실행하려면 throughput
서브커맨드를 사용합니다. PyTorch 플로우를 이용해 벤치마크를 실행하려면 TensorRT-LLM이 설치된 환경에서 아래 명령을 실행하면 됩니다.
trtllm-bench throughput \
--model meta-llama/Llama-3.1-8B-Instruct \
--dataset dataset.jsonl \
--tp 1 \
--backend pytorch \
--report_json results.json
--streaming \
--concurrency $CONCURRENCY
throughput
명령은 HuggingFace에서 체크포인트를 자동으로 가져오고(캐시에 없을 경우), PyTorch 플로우로 TRT-LLM을 부트스트랩합니다. 실행이 완료되면 결과가 results.json
에 저장되고, 아래와 같이 터미널에도 출력됩니다.
참고: 아래 예시는 단순 샘플 출력이며, 실제 성능 수치를 나타내지 않습니다.
===========================================================
= PYTORCH BACKEND
===========================================================
Model: meta-llama/Llama-3.1-8B-Instruct
Model Path: None
TensorRT-LLM Version: 0.21.0rc0
Dtype: bfloat16
KV Cache Dtype: None
Quantization: None
===========================================================
= REQUEST DETAILS
===========================================================
Number of requests: 100
Number of concurrent requests: 94.6050
Average Input Length (tokens): 128.0000
Average Output Length (tokens): 128.0000
===========================================================
= WORLD + RUNTIME INFORMATION
===========================================================
TP Size: 1
PP Size: 1
EP Size: None
Max Runtime Batch Size: 3840
Max Runtime Tokens: 7680
Scheduling Policy: GUARANTEED_NO_EVICT
KV Memory Percentage: 90.00%
Issue Rate (req/sec): 1.0526E+15
===========================================================
= PERFORMANCE OVERVIEW
===========================================================
Request Throughput (req/sec): 86.5373
Total Output Throughput (tokens/sec): 11076.7700
Total Token Throughput (tokens/sec): 22153.5399
Total Latency (ms): 1155.5715
Average request latency (ms): 1093.2284
Per User Output Throughput [w/ ctx] (tps/user): 117.1544
Per GPU Output Throughput (tps/gpu): 11076.7700
Average time-to-first-token [TTFT] (ms): 162.6706
Average time-per-output-token [TPOT] (ms): 7.3272
Per User Output Speed (tps/user): 137.1475
-- Per-Request Time-per-Output-Token [TPOT] Breakdown (ms)
[TPOT] MINIMUM: 6.6450
[TPOT] MAXIMUM: 8.1306
[TPOT] AVERAGE: 7.3272
[TPOT] P50 : 7.6079
[TPOT] P90 : 8.1246
[TPOT] P95 : 8.1289
[TPOT] P99 : 8.1306
-- Per-Request Time-to-First-Token [TTFT] Breakdown (ms)
[TTFT] MINIMUM: 93.9210
[TTFT] MAXIMUM: 232.4339
[TTFT] AVERAGE: 162.6706
[TTFT] P50 : 159.7857
[TTFT] P90 : 220.0530
[TTFT] P95 : 226.9148
[TTFT] P99 : 232.4339
-- Per-Request Generation Throughput [GTPS] Breakdown (tps/user)
[GTPS] MINIMUM: 122.9921
[GTPS] MAXIMUM: 150.4894
[GTPS] AVERAGE: 137.1475
[GTPS] P50 : 131.4444
[GTPS] P90 : 150.4112
[GTPS] P95 : 150.4606
[GTPS] P99 : 150.4894
-- Request Latency Breakdown (ms) -----------------------
[Latency] P50 : 1091.7905
[Latency] P90 : 1130.7200
[Latency] P95 : 1133.0074
[Latency] P99 : 1137.6817
[Latency] MINIMUM: 1050.1519
[Latency] MAXIMUM: 1137.6817
[Latency] AVERAGE: 1093.2284
===========================================================
= DATASET DETAILS
===========================================================
Dataset Path: /workspace/benchmark_toolkit/synthetic_data.jsonl
Number of Sequences: 100
-- Percentiles statistics ---------------------------------
Input Output Seq. Length
-----------------------------------------------------------
MIN: 128.0000 128.0000 256.0000
MAX: 128.0000 128.0000 256.0000
AVG: 128.0000 128.0000 256.0000
P50: 128.0000 128.0000 256.0000
P90: 128.0000 128.0000 256.0000
P95: 128.0000 128.0000 256.0000
P99: 128.0000 128.0000 256.0000
===========================================================
성능 결과 분석
위 명령을 실행하면 주요 통계는 PERFORMANCE OVERVIEW
섹션에 표시됩니다. 세부 내용에 들어가기 전에 몇 가지 용어를 정리하면 다음과 같습니다.
Output
: 컨텍스트 토큰을 포함한 모든 출력 토큰(tocken
)Total Token
: 생성된 전체 시퀀스 길이 (ISL + OSL)Per user
,TTFT
,TPOT
: 각 요청을 하나의 “사용자”로 간주해 계산한 통계이며, 이를 기반으로 분포 형성
더 자세한 설명은 이 시리즈의 첫 번째 글인 LLM Inference Benchmarking: Fundamental Concepts를 참고하세요.
===========================================================
= PERFORMANCE OVERVIEW
===========================================================
Request Throughput (req/sec): 86.5373
Total Output Throughput (tokens/sec): 11076.7700
Total Token Throughput (tokens/sec): 22153.5399
Total Latency (ms): 1155.5715
Average request latency (ms): 1093.2284
Per User Output Throughput [w/ ctx] (tps/user): 117.1544
Per GPU Output Throughput (tps/gpu): 11076.7700
Average time-to-first-token [TTFT] (ms): 162.6706
Average time-per-output-token [TPOT] (ms): 7.3272
Per User Output Speed (tps/user): 137.1475
또한 trtllm-bench
는 처리 가능한 최대 토큰 수와 최대 배치 크기도 함께 표시합니다.
===========================================================
= WORLD + RUNTIME INFORMATION
===========================================================
TP Size: 1
PP Size: 1
EP Size: None
Max Runtime Batch Size: 3840
Max Runtime Tokens: 7680
이 값들은 TensorRT-LLM에서 다음과 같은 의미를 가집니다.
- 최대 토큰 수(Max Tokens): 엔진이 한 번의 배치 처리에서 다룰 수 있는 최대 토큰 수를 의미합니다. 이 값에는 모든 컨텍스트 요청의 입력 토큰 합과, 배치 내 모든 생성 요청의 토큰 합 중 최소 1토큰이 포함됩니다.
- 최대 배치 크기(Max Batch Size): 한 배치에서 허용되는 최대 요청 수를 의미합니다. 예를 들어, 한 번의 반복(iteration)에 컨텍스트 길이가 128인 요청 하나와, 4개의 생성 요청(총 132토큰)이 있다고 가정합니다. 최대 토큰 수를 512로, 최대 배치 크기를 5로 설정하면, 토큰 한도에 도달하지 않았더라도 엔진은 배치 크기 한도에서 처리를 멈춥니다.
결과를 분석할 때는 무엇을 우선할지를 명확히 아는 것이 중요합니다. 예를 들어:
- 사용자당 토큰 처리량을 높이는 것이 목표인가?
- 대규모 텍스트 처리에서 최대 처리량을 확보하는 것이 중요한가?
- 첫 토큰을 최대한 빨리 반환하는 것이 중요한가?
튜닝 전략은 우선순위에 따라 달라집니다. 이번 글에서는 사용자 경험 최적화하는 데 초점을 맞춥니다. 특히, 컨텍스트 단계가 끝난를 마친 후 사용자에게 토큰이 반환되는 속도인 Per User Output Speed
지표를 가장 중요하게 다룹니다. trtllm-bench
에서는 --concurrency
옵션을 사용해 동시에 처리할 최대 요청 수를 지정할 수 있으며, 이를 통해 시스템이 지원할 수 있는 사용자 수를 조정할 수 있습니다.
이 옵션은 지연 시간(latency)과 처리량(throughput) 목표를 찾는 데 중요한 다양한 곡선을 생성하는 데 유용합니다. 예를 들어, 128/128 ISL/OSL 시나리오에서 NVIDIA Llama-3.1 8B FP8과 Meta Llama-3.1 8B FP16을 기준으로 만든 곡선 세트를 살펴봅시다. 만약 시스템 활용도를 최대한 끌어올리면서도 사용자가 초당 약 50토큰(토큰 간 약 20ms)의 출력 속도를 경험하도록 하고 싶다면, GPU 성능과 사용자 경험 간의 균형을 따져야 합니다. 이때는 GPU당 출력 처리량과 사용자당 출력 속도를 함께 그래프로 비교해 볼 수 있습니다.

그림 1에서 보면 Llama-3.1 8B FP16 모델은 약 256명의 동시 사용자에서 초당 약 72토큰 처리 속도를 유지하며, 이 지점에서 초당 50토큰이라는 기준을 충족합니다. 반면, Llama-3.1 8B FP8 최적화 체크포인트는 약 66토큰/초/사용자 속도로 512명의 동시 사용자를 처리할 수 있습니다. 즉, trtllm-bench
로 두 모델을 비교해본 결과, 양자화된 모델이 동일한 리소스 예산에서 더 많은 사용자를 지원할 수 있다는 결론을 얻을 수 있습니다.
이 데이터를 바탕으로 다음과 같은 점을 고려할 수 있습니다.
- 엔진을 강제로 512 항목으로 맞추고 싶다면 최대 배치 크기(max batch size)를 512로 설정할 수 있습니다. 하지만 이렇게 하면 해당 인스턴스의 트래픽이 512를 초과할 경우 초과 요청이 대기열에 들어가 첫 토큰 출력 시간(TTFT)이 늘어날 위험이 있습니다.
trtllm-bench
를 사용하면 다른 데이터셋과 모델로 다양한 QoS(서비스 품질) 시나리오를 테스트하고, 여러 지표를 시각화해볼 수 있습니다. 이 툴은 간단한 명령어 조정을 통해, 우선순위에 맞춘 성능 평가를 쉽게 진행할 수 있도록 해줍니다.
참고: 이번 시나리오에서는 단일 GPU 모델만 다루었지만, 멀티 GPU가 필요한 경우 trtllm-bench
에서 --tp
, --pp
, --ep
옵션을 사용해 최적의 샤딩·데이터 병렬 구성을 찾을 수 있습니다. 또한, 개발자라면 --extra_llm_api_options
인자를 활용해 고급 기능을 적용할 수 있습니다.
trtllm-serve로 거대 언어 모델 서빙하기
TensorRT-LLM은 trtllm-serve
명령으로 OpenAI 호환 엔드포인트를 손쉽게 띄울 수 있게 해줍니다. 위에서 trtllm-bench
로 얻은 튜닝 값을 그대로 가져와 튜닝된 서버를 구동할 수 있습니다. 벤치마크 단계와 달리, trtllm-serve
는 일반 설정을 제외하고는 구성에 대해 가정을 두지 않습니다. 위의 최대 처리량 결과를 기준으로 서버를 튜닝하려면, 아래 출력값을 바탕으로 다음 명령을 제공하면 됩니다:
trtllm-serve serve nvidia/Llama-3.1-8B-Instruct-FP8 --backend pytorch --max_num_tokens 7680 --max_batch_size 3840 --tp_size 1 --extra_llm_api_options llm_api_options.yml
--extra_llm_api_options
는 LLM API 레벨에서 설정을 직접 변경할 수 있는 방법을 제공합니다. 벤치마크에서 사용한 설정과 동일하게 맞추려면, llm_api_options.yml
에 다음 내용을 포함해야 합니다.
cuda_graph_config:
max_batch_size: 3840
padding_enabled: true
설정을 마치고 실행하면, 서버가 실행 중임을 나타내는 상태 메시지가 표시됩니다.
INFO: Application startup complete.
INFO: Uvicorn running on http://localhost:8000 (Press CTRL+C to quit)
서버가 실행되면, 이제 GenAI-Perf(이 시리즈의 두 번째 글에서 다룬 방법과 유사)를 사용하거나, 포팅된 benchmark_serving.py 스크립트를 이용해 모델 벤치마크를 진행할 수 있습니다. 이를 통해 튜닝된 서버 설정의 성능을 검증할 수 있습니다. 향후 릴리스에서는 trtllm-bench
에서 바로 최적화된 서버를 실행해 벤치마크할 수 있는 기능이 추가될 예정입니다.
LLM 벤치마킹 및 성능 튜닝 시작하기
trtllm-bench
는 다양한 설정, 튜닝 옵션, 동시성, 기능을 손쉽게 벤치마크할 수 있는 방법을 제공합니다. trtllm-bench
에서 얻은 설정은 TensorRT-LLM의 네이티브 서빙 솔루션인 trtllm-serve
로 그대로 옮길 수 있으며, 이를 통해 성능 튜닝 결과를 OpenAI 호환 배포 환경에 매끄럽게 적용할 수 있습니다.
성능, 모델별 튜닝, 그리고 TensorRT-LLM의 튜닝·벤치마킹에 대한 더 자세한 정보는 다음 자료를 참고하세요.
- 성능 옵션을 더 깊이 이해하려면 Performance Tuning Guide를 확인하세요.
trtllm-bench
문서는 Performance Benchmarking 페이지에서 확인할 수 있습니다.- TensorRT-LLM 프로파일링 방법은 Performance Analysis에서 Nsight System을 활용한 모델 실행 프로파일링 절차를 다룹니다.
- DeepSeek-R1 성능 튜닝에 대한 심층 내용은 TensorRT-LLM Performance Tuning Guide for DeepSeek-R1를 참고하세요.
또한, 다음 자료도 확인해 보세요.
- 플랫폼 아키텍처가 FLOPS 이상의 TCO에 미치는 영향을 알아보려면 블로그 글 “NVIDIA DGX Cloud Introduces Ready-To-Use Templates to Benchmark AI Platform Performance”를 읽어보세요. NGC에서 다운로드 가능한 즉시 사용 가능한 템플릿 모음도 확인하세요.
- The IT Leader’s Guide to AI Inference and Performance에서는 토큰당 비용을 절감하고 AI 모델을 최대한 활용하는 방법을 배울 수 있습니다.