vLLM 프로파일링

vLLM 프로파일링 (Profiling vLLM)

!!! warning 프로파일링은 vLLM 개발자·메인테이너가 코드베이스의 여러 부분에서 시간이 어떻게 분배되는지 이해하기 위한 목적만 있어요. vLLM 최종 사용자는 절대 프로파일링을 켜면 안 돼요. 추론을 크게 느려지게 만들기 때문이에요.

!!! tip "프로파일러 고르기" - Nsight Systems는 오버헤드가 낮고 성능에 민감한 프로파일링에 사용해요. - PyTorch Profiler는 중간 오버헤드로 더 풍부한 디버깅 정보(스택 트레이스, 메모리, 형태 등)를 원할 때 사용해요. 이런 기능을 켜면 오버헤드가 추가되고 벤치마킹에는 권장되지 않아요.

PyTorch Profiler로 프로파일링하기 (Profile with PyTorch Profiler)

vLLM 워커는 다양한 프로파일러로 트레이싱할 수 있어요. 서버를 시작할 때 --profiler-config 플래그를 설정하면 프로파일링을 켤 수 있어요.

!!! note --profiler-config 플래그는 vLLM v0.13.0 이상에서 사용할 수 있어요. 이전 버전을 쓰고 있다면 이 기능을 쓰려면 업그레이드하세요.

torch.profiler 모듈을 쓰려면 config의 profiler 항목을 'torch'로, torch_profiler_dir을 트레이스를 저장할 디렉터리로 설정하세요. 또한 config에서 다음 추가 인자를 지정해 프로파일링 내용을 제어할 수 있어요:

  • torch_profiler_record_shapes: Tensor 형태 기록 켜기, 기본 꺼짐
  • torch_profiler_with_memory: 메모리 기록, 기본 꺼짐
  • torch_profiler_with_stack: 스택 정보 기록 켜기, 기본 켜짐
  • torch_profiler_with_flops: FLOPs 기록 켜기, 기본 꺼짐
  • torch_profiler_use_gzip: 프로파일링 파일을 gzip 압축할지 제어, 기본 켜짐
  • torch_profiler_dump_cuda_time_total: 집계된 CUDA self time 표를 덤프·출력할지 제어, 기본 켜짐

vllm bench serve를 쓸 때는 --profile 플래그를 넘겨 프로파일링을 켤 수 있어요.

트레이스는 https://ui.perfetto.dev/로 시각화할 수 있어요.

!!! tip vLLM을 설치하지 않고도 python -m vllm.entrypoints.cli.main bench로 bench 모듈을 직접 호출할 수 있어요.

!!! tip 프로파일링할 때는 vLLM에 요청 몇 개만 보내세요. 트레이스가 아주 커질 수 있어요. 트레이스를 untar할 필요도 없고 바로 볼 수 있어요.

!!! tip 프로파일러를 멈추면 모든 프로파일 트레이스 파일을 디렉터리에 플러시해요. 이 작업은 시간이 걸려요. 예를 들어 llama 70b의 요청 약 100개 분량 데이터는 H100에서 플러시하는 데 약 10분이 걸려요. 엔진 클라이언트는 타임아웃 없이 이 플러시 완료를 기다리므로, 그냥 stop 호출이 끝까지 실행되도록 두면 돼요.

예시 명령과 사용법 (Example commands and usage)

오프라인 추론 (Offline Inference)

예시는 examples/features/profiling/simple_profiling_offline.py를 참고하세요.

OpenAI 서버 (OpenAI Server)

vllm serve meta-llama/Llama-3.1-8B-Instruct --profiler-config '{"profiler": "torch", "torch_profiler_dir": "./vllm_profile"}'

vllm bench 명령:

vllm bench serve \
    --backend vllm \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --dataset-name sharegpt \
    --dataset-path sharegpt.json \
    --profile \
    --num-prompts 2

또는 http 요청 사용:

# We need first call /start_profile api to start profile.
$ curl -X POST http://localhost:8000/start_profile

# Call model generate.
curl -X POST http://localhost:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
                "model": "meta-llama/Llama-3.1-8B-Instruct",
                "messages": [
                        {
                                "role": "user",
                                "content": "San Francisco is a"
                        }
                ]
    }'

# After need call /stop_profile api to stop profile.
$ curl -X POST http://localhost:8000/stop_profile

Triton Proton으로 프로파일링하기 (Profile with Triton Proton)

Proton은 Triton의 GPU 프로파일러예요. 낮은 오버헤드의 집계 트리 또는 Chrome 트레이스를 수집할 수 있고, PyTorch·CUDA 프로파일러와 동일한 vLLM 프로파일링 제어를 통해 작동해요. Proton은 현재 CUPTI를 통해 NVIDIA GPU를 지원하며 eager 실행이 필요해요.

로컬 출력 디렉터리로 서버를 시작해요:

vllm serve meta-llama/Llama-3.1-8B-Instruct \
    --enforce-eager \
    --profiler-config '{
        "profiler": "proton",
        "proton_profiler_dir": "./proton_profile",
        "proton_output_format": "hatchet",
        "proton_hook": "triton"
    }'

그런 다음 위처럼 /start_profile/stop_profile을 쓰거나 vLLM 벤치마크에 --profile을 넘겨요. 각 워커는 토폴로지·랭크로 한정된 출력 이름을 사용해요(예: proton_dp0_pp0_tp0_dcp0_ep0_rank0_pid1234_0123456789abcdef0123456789abcdef_run0.hatchet). 그래서 분산 워커, 재시작된 서버, 반복된 프로파일링 실행이 서로를 덮어쓰지 않아요. profile_prefix가 제공되면 포함돼요. 각 프로파일은 /stop_profile으로 마무리되고 즉시 검사할 준비가 돼요.

Proton 전용 옵션은 다음과 같아요:

  • proton_context: shadow(기본) 또는 python
  • proton_data: tree(기본) 또는 trace
  • proton_backend: cupti 또는 자동
  • proton_mode: 선택적 백엔드 모드 문자열
  • proton_hook: Triton 실행 메타데이터를 기록하려면 triton, 아니면 미설정
  • proton_output_format: hatchet, hatchet_msgpack, chrome_trace, 또는 미설정

hatchethatchet_msgpackproton_data: "tree"가 필요하고, chrome_traceproton_data: "trace"가 필요해요. CUDA graph 프로파일링은 아직 지원되지 않으므로 모든 Proton 모드에 --enforce-eager가 필요해요.

자동 백엔드 선택을 권장해요. vLLM은 현재 NVIDIA GPU에서 Proton의 cupti 백엔드를 지원해요. ROCm 지원은 아직 없어요. vLLM은 Proton의 실험적 계측 백엔드를 노출하지 않아요. 현재 업스트림 Triton 빌드가 타이밍 메트릭 없이 프로파일을 생성할 수 있기 때문이에요. pcsampling을 포함한 백엔드별 모드는 proton_mode로 선택할 수 있어요.

Triton 3.6은 명시적 hatchet·chrome_trace 출력을 지원해요. hatchet_msgpack 형식과 periodic_flushing 모드는 Triton 3.7 이상이 필요해요. vLLM은 세션을 시작하기 전에 감지된 버전으로 이 옵션들을 거부해요.

트리 프로파일을 다음 명령으로 검사해요:

proton-viewer -m time/ns \
    proton_profile/proton_dp0_pp0_tp0_dcp0_ep0_rank0_pid1234_0123456789abcdef0123456789abcdef_run0.hatchet

Chrome 트레이스(proton_data: "trace")는 https://ui.perfetto.dev/에서 열 수 있어요. Proton은 지연 import되므로 다른 프로파일러를 선택하면 Proton 호환 Triton 설치가 필요하지 않아요.

NVIDIA Nsight Systems로 프로파일링하기 (Profile with NVIDIA Nsight Systems)

Nsight Systems는 레지스터·공유 메모리 사용량, 주석이 달린 코드 영역, 저수준 CUDA API·이벤트 같은 더 많은 프로파일링 세부사항을 노출하는 고급 도구예요.

nsight-systems 설치를 패키지 매니저로 해요. 아래 블록은 Ubuntu 예시예요.

apt update
apt install -y --no-install-recommends gnupg
echo "deb http://developer.download.nvidia.com/devtools/repos/ubuntu$(source /etc/lsb-release; echo "$DISTRIB_RELEASE" | tr -d .)/$(dpkg --print-architecture) /" | tee /etc/apt/sources.list.d/nvidia-devtools.list
apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
apt update
apt install nsight-systems-cli

!!! tip nsys로 프로파일링할 때는 환경변수 VLLM_WORKER_MULTIPROC_METHOD=spawn을 설정하는 것이 좋아요. 기본값은 spawn 대신 fork 메서드를 사용해요. 자세한 내용은 Nsight Systems 릴리스 노트에서 볼 수 있어요.

Nsight Systems 프로파일러는 nsys profile ...로 실행할 수 있고, vLLM 권장 플래그는 --trace-fork-before-exec=true --cuda-graph-trace=node예요.

예시 명령과 사용법 (Example commands and usage)

오프라인 추론 (Offline Inference)

기본 사용법은 오프라인 추론에 대해 실행하던 기존 스크립트 앞에 프로파일링 명령을 붙이면 돼요.

다음은 vllm bench latency 스크립트를 사용한 예시예요:

nsys profile  \
    --trace-fork-before-exec=true \
    --cuda-graph-trace=node \
vllm bench latency \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --num-iters-warmup 5 \
    --num-iters 1 \
    --batch-size 16 \
    --input-len 512 \
    --output-len 8

OpenAI 서버 (OpenAI Server)

서버를 프로파일링하려면 오프라인 추론처럼 vllm serve 명령 앞에 nsys profile을 붙이면 돼요. 다만 Torch Profiler와 유사하게 동적 캡처를 켜려면 몇 가지 다른 인자를 지정해야 해요:

# server
nsys profile \
    --trace-fork-before-exec=true \
    --cuda-graph-trace=node \
    --capture-range=cudaProfilerApi \
    --capture-range-end repeat \
    vllm serve meta-llama/Llama-3.1-8B-Instruct --profiler-config.profiler cuda

# client
vllm bench serve \
    --backend vllm \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --dataset-name sharegpt \
    --dataset-path sharegpt.json \
    --profile \
    --num-prompts 2

--profile을 쓰면 vLLM은 vllm bench serve의 각 실행에 대해 프로파일을 캡처해요. 서버가 죽으면 모든 프로파일이 저장돼요.

분석 (Analysis)

이 프로파일들은 CLI에서 nsys stats [profile-file]로 요약으로 보거나, Nsight를 여기 지침대로 로컬에 설치해 GUI에서 볼 수 있어요.

??? console "CLI example"

```bash
nsys stats report1.nsys-rep
...
** CUDA GPU Kernel Summary (cuda_gpu_kern_sum):

Time (%)  Total Time (ns)  Instances   Avg (ns)     Med (ns)    Min (ns)  Max (ns)   StdDev (ns)                                                  Name
--------  ---------------  ---------  -----------  -----------  --------  ---------  -----------  ----------------------------------------------------------------------------------------------------
    46.3   10,327,352,338     17,505    589,965.9    144,383.0    27,040  3,126,460    944,263.8  sm90_xmma_gemm_bf16bf16_bf16f32_f32_tn_n_tilesize128x128x64_warpgroupsize1x1x1_execute_segment_k_of…
    14.8    3,305,114,764      5,152    641,520.7    293,408.0   287,296  2,822,716    867,124.9  sm90_xmma_gemm_bf16bf16_bf16f32_f32_tn_n_tilesize256x128x64_warpgroupsize2x1x1_execute_segment_k_of…
    12.1    2,692,284,876     14,280    188,535.4     83,904.0    19,328  2,862,237    497,999.9  sm90_xmma_gemm_bf16bf16_bf16f32_f32_tn_n_tilesize64x128x64_warpgroupsize1x1x1_execute_segment_k_off…
    9.5    2,116,600,578     33,920     62,399.8     21,504.0    15,326  2,532,285    290,954.1  sm90_xmma_gemm_bf16bf16_bf16f32_f32_tn_n_tilesize64x64x64_warpgroupsize1x1x1_execute_segment_k_off_…
    5.0    1,119,749,165     18,912     59,208.4      9,056.0     6,784  2,578,366    271,581.7  void vllm::act_and_mul_kernel<c10::BFloat16, &vllm::silu_kernel<c10::BFloat16>, (bool)1>(T1 *, cons…
    4.1      916,662,515     21,312     43,011.6     19,776.0     8,928  2,586,205    199,790.1  void cutlass::device_kernel<flash::enable_sm90_or_later<flash::FlashAttnFwdSm90<flash::CollectiveMa…
    2.6      587,283,113     37,824     15,526.7      3,008.0     2,719  2,517,756    139,091.1  std::enable_if<T2>(int)0&&vllm::_typeConvert<T1>::exists, void>::type vllm::fused_add_rms_norm_kern…
    1.9      418,362,605     18,912     22,121.5      3,871.0     3,328  2,523,870    175,248.2  void vllm::rotary_embedding_kernel<c10::BFloat16, (bool)1>(const long *, T1 *, T1 *, const T1 *, in…
    0.7      167,083,069     18,880      8,849.7      2,240.0     1,471  2,499,996    101,436.1  void vllm::reshape_and_cache_flash_kernel<__nv_bfloat16, __nv_bfloat16, (vllm::Fp8KVCacheDataType)0…
...
```

연속 프로파일링 (Continuous Profiling)

PyTorch 인프라 저장소에 vLLM의 다양한 모델에 대한 연속 프로파일링을 제공하는 GitHub CI 워크플로가 있어요. 이 자동화된 프로파일링은 시간과 다양한 모델 구성에 걸친 성능 특성을 추적하는 데 도움을 줘요.

작동 방식 (How It Works)

워크플로는 현재 선택된 모델에 대해 주간 프로파일링 세션을 실행해 성능 회귀·최적화 기회를 식별하기 위해 다른 도구로 분석할 수 있는 상세한 성능 트레이스를 생성해요. 하지만 Github Action 도구로 수동으로도 트리거할 수 있어요.

새 모델 추가 (Adding New Models)

연속 프로파일링을 추가 모델로 확장하려면 PyTorch 통합 테스트 저장소의 profiling-tests.json 구성 파일을 수정하면 돼요. 모델 사양을 이 파일에 추가하면 자동 프로파일링 실행에 포함돼요.

프로파일링 결과 보기 (Viewing Profiling Results)

연속 프로파일링 워크플로가 생성한 프로파일링 트레이스는 vLLM Performance Dashboard에서 공개적으로 사용할 수 있어요. Profiling traces 표를 찾아 다양한 모델·실행의 트레이스를 접근·다운로드하면 돼요.

vLLM Python 코드 프로파일링하기 (Profiling vLLM Python Code)

Python 표준 라이브러리에는 Python 코드를 프로파일링하기 위한 cProfile이 포함되어 있어요.

예시 사용법 - 함수 호출

파일명을 지정하면 프로파일이 그 파일에 저장돼요. 파일명을 지정하지 않으면 프로파일 데이터가 표준 출력으로 인쇄돼요.

import cProfile


def expensive_function():
    # some expensive code
    pass


profiler = cProfile.Profile()
profiler.runcall(expensive_function)
profiler.dump_stats("expensive_function.prof")

예시 사용법 - 컨텍스트 매니저 스타일

import cProfile


def another_function():
    # more expensive code
    pass


profiler = cProfile.Profile()
profiler.enable()
try:
    another_function()
finally:
    profiler.disable()
    profiler.dump_stats("another_function.prof")

프로파일 결과 분석하기 (Analyzing Profile Results)

프로파일 결과를 분석하는 데 도움을 주는 도구가 여러 가지 있어요. 예를 들어 snakeviz가 있어요.

pip install snakeviz
snakeviz expensive_function.prof

가비지 컬렉션 비용 분석하기 (Analyzing Garbage Collection Costs)

VLLM_GC_DEBUG 환경변수를 활용해 GC 비용을 디버깅해요.

  • VLLM_GC_DEBUG=1: gc.collect 경과 시간으로 GC 디버거 켜기
  • VLLM_GC_DEBUG='{"top_objects":5}': 각 gc.collect에서 수집된 상위 5개 객체를 기록하도록 GC 디버거 켜기

출처: 공식문서

더 알아보기 (Learn more)