성능 프로파일링
성능 프로파일링 (Performance Profiling)
추론 서빙 중에는 때때로 서빙 프레임워크의 내부 실행 흐름을 모니터링해 성능 문제를 파악해야 할 때가 있어요. 핵심 흐름의 시작/종료 타임스탬프를 수집하고, 중요한 함수나 반복을 식별하며, 주요 이벤트를 기록하고 관련 정보를 모으면 성능 병목을 빠르게 찾을 수 있어요.
출처: 문서
본문
이 가이드는 SGLang Ascend NPU 추론 서비스에서 성능 데이터를 수집하는 전체 워크플로우 — 준비, 수집, 분석에서 시각화까지 — 를 안내해요. 성능 프로파일링을 빠르게 시작하는 데 도움이 될 거예요.
더 많은 프로파일링 시나리오(예: Nsight Systems, PD 분리 등)는 SGLang Benchmark and Profiling 을 참고하세요.
Ascend PyTorch Profiler
SGLang에는 내장 PyTorch Profiler 지원이 있어요. Ascend torch_npu 백엔드를 통해 NPU 연산자 레벨 성능 데이터를 직접 수집할 수 있어요. 추가 패키지가 필요 없어요 — 프로파일링 시작/종료는 API 요청으로 제어돼요.
1. 환경 설정 (Environment Setup)
SGLang 온라인 서비스를 실행하고 SGLANG_TORCH_PROFILER_DIR 환경 변수를 설정해 성능 파일 저장 위치를 제어하세요. 서비스가 시작되면 프로파일링이 대기 상태로 준비돼요.
# 성능 데이터 출력 디렉토리 설정
export SGLANG_TORCH_PROFILER_DIR=./sglang_profile
# SGLang 서버 시작 (로컬 모델 경로 또는 HuggingFace 모델 id 사용)
sglang serve \
--model-path /path/to/your/model \
--attention-backend ascend \
--host 0.0.0.0 --port 30000 \
--tp-size 1 \
--max-running-requests 128
프로파일링 관련 환경 변수:
| 변수 | 설명 | 기본값 |
|---|---|---|
SGLANG_TORCH_PROFILER_DIR |
트레이스 파일 출력 디렉토리 | /tmp |
SGLANG_PROFILE_WITH_STACK |
Python 호출 스택 기록 (True / False) | True |
SGLANG_PROFILE_RECORD_SHAPES |
연산자 입력 형태 기록 (True / False) | True |
우선순위: API 파라미터 > 환경 변수 > 기본값.
2. 수집 방법 (Collection Methods)
SGLang은 네 가지 수집 방법을 제공해요. 핵심 차이는 /start_profile과 /stop_profile을 수동으로 보내야 하는지 여부예요. 네 방법 모두 동일한 결과를 만들어요 — 가장 편한 방법을 선택하세요.
방법 비교:
| 방법 | 수동 start_profile | 수동 stop_profile | 참고 |
|---|---|---|---|
| A: API 수동 시작/종료 | 예 | 예 | 정밀한 제어를 위한 최대 유연성 |
| B: API 자동 종료 | 예 | 아니요 | num\_steps 설정, 자동 종료 및 출력 생성 |
| C: bench_serving --profile | 아니요 | 아니요 | 벤치마크 + 프로파일링 한 번에 |
| D: sglang.profiler CLI | 아니요 | 아니요 | 독립 프로파일링 CLI 도구 |
방법 A: API 수동 시작/종료 (Method A: API Manual Start/Stop)
/start_profile을 보내 시작 → 작업 부하 요청 전송 → /stop_profile을 보내 종료해요. 종료 후 서버가 데이터를 자동으로 파싱해요 — analyse()를 수동으로 호출할 필요가 없어요.
# 1단계: 프로파일링 시작 (num_steps 없음, 수동 종료 필요)
curl -X POST http://127.0.0.1:30000/start_profile \
-H "Content-Type: application/json" \
-d '{
"output_dir": "./sglang_profile",
"start_step": 1,
"activities": ["CPU", "GPU"]
}'
# 2단계: 작업 부하 요청 전송 (curl을 예시로)
curl http://127.0.0.1:30000/generate \
-H "Content-Type: application/json" \
-d '{"text": "Hello", "sampling_params": {"max_new_tokens": 10}}'
# 3단계: 프로파일링 종료
curl -X POST http://127.0.0.1:30000/stop_profile
/stop_profile은"Stop profiling. This will take some time."을 반환해요 — 서버가 트레이스 데이터를 디스크로 플러시하고 파싱하는 시간이 필요해요. 응답이 완료될 때까지 기다리세요. 이 방법은 프로파일링 데이터 파싱에 상당한 시간이 걸려요. 긴 대기를 피하려면 방법 B를 사용하는 것이 좋아요.
방법 B: API 자동 종료 (Method B: API Auto-Stop)
/start_profile 요청에서 num_steps를 지정해요. N 스텝 후 프로파일링이 자동으로 종료되고 출력을 생성해요 — /stop_profile을 수동으로 보낼 필요가 없어요.
# num_steps=10, 워밍업 3 스텝 대기, 10 스텝 후 자동 종료
curl -X POST http://127.0.0.1:30000/start_profile \
-H "Content-Type: application/json" \
-d '{
"output_dir": "./sglang_profile",
"start_step": 3,
"num_steps": 10,
"activities": ["CPU", "GPU"]
}'
# 작업 부하만 전송 — /stop_profile 불필요
curl http://127.0.0.1:30000/generate \
-H "Content-Type: application/json" \
-d '{"text": "Hello", "sampling_params": {"max_new_tokens": 32}}'
방법 C: bench_serving --profile (Method C: bench_serving --profile)
SGLang 내장 bench_serving을 --profile 플래그와 함께 사용하세요. /start_profile과 /stop_profile을 자동으로 처리해요 — 수동 API 호출이 필요 없어요.
# --profile-steps 사용: N 스텝 후 자동 종료 및 출력 생성
python -m sglang.bench_serving \
--backend sglang \
--base-url http://127.0.0.1:30000 \
--model /path/to/your/model \
--tokenizer /path/to/your/model \
--dataset-name random \
--random-input-len 1024 \
--random-output-len 100 \
--num-prompts 10 \
--profile \
--profile-steps 10 \
--profile-output-dir ./sglang_profile
# --profile-steps 없이: 벤치마크 후 /stop_profile 자동 전송
python -m sglang.bench_serving \
--backend sglang \
--base-url http://127.0.0.1:30000 \
--model /path/to/your/model \
--tokenizer /path/to/your/model \
--dataset-name random \
--random-input-len 1024 \
--random-output-len 100 \
--num-prompts 10 \
--profile \
--profile-output-dir ./sglang_profile
--profile-steps N은 서버의/start_profile에"num_steps": N을 보내므로, N 스텝 후 서버가 자동으로 종료하고 데이터를 파싱해요 — bench_serving은/stop_profile전송을 건너뛰어요.
bench_serving --profile은--profile-output-dir안에 타임스탬프 서브디렉토리를 만들어요(예:<output_dir>/<timestamp>/). 출력 경로는 서버 로그에Profiling done. Traces are saved to: <path>로 표시돼요.
Ascend NPU에서 SGLang은
torch_npu._apply_patches()로 PyTorch Profiler의 CUDA 액티비티를 자동으로 NPU로 리다이렉트하므로,activities: ["CPU", "GPU"]가 실제로 NPU 연산자 이벤트를 캡처해요.
bench_serving --profile 파라미터:
| 파라미터 | 설명 |
|---|---|
--profile |
자동 프로파일링 시작/종료 활성화 |
--profile-steps N |
N 스텝 후 자동 종료 (/stop_profile 생략) |
--profile-output-dir |
트레이스 출력 디렉토리 |
방법 D: sglang.profiler CLI
/start_profile을 자동으로 보내고 완료를 기다리는 sglang.profiler CLI 모듈을 사용하세요. sglang.profiler를 먼저 시작하고, 그 다음 추론 요청을 보내세요 (그렇지 않으면 캡처할 스텝이 없어 프로파일러가 무한히 대기해요).
# 터미널 1: 먼저 sglang.profiler 시작 (/start_profile 전송 후 완료 대기)
python3 -m sglang.profiler \
--url http://127.0.0.1:30000 \
--output-dir ./my_profiles \
--num-steps 3 \
--cpu --gpu &
# 터미널 2: 터미널 1에서 "Waiting for N steps" 출력을 기다린 후 요청 전송.
# 서버가 /start_profile을 받으면 프로파일러가 기록을 시작.
# 서버가 /start_profile을 받기 전에 보낸 요청은 캡처되지 않음.
curl http://127.0.0.1:30000/generate \
-H "Content-Type: application/json" \
-d '{"text": "Hello", "sampling_params": {"max_new_tokens": 32}}'
더 간단하고 안정적인 방법은 bench_serving --profile을 사용하는 거예요. 이 도구가 두 단계를 모두 자동으로 처리해요:
python3 -m sglang.bench_serving \
--backend sglang \
--base-url http://127.0.0.1:30000 \
--model /path/to/your/model \
--tokenizer /path/to/your/model \
--dataset-name random \
--random-input-len 128 \
--random-output-len 32 \
--num-prompts 10 \
--profile \
--profile-steps 3 \
--profile-output-dir ./my_profiles
sglang.profiler는 본질적으로/start_profileAPI를 감싼 CLI 래퍼예요.--profile-by-stage같은 고급 옵션도 지원돼요. Ascend NPU에서 트레이스 플러시는 비동기적이며 시간이 걸릴 수 있어요 — CLI가 플러시를 기다리며 가끔 블록될 수 있어요. 타임아웃되면 방법 B(API 자동 종료)나 방법 C(bench_serving --profile)를 대신 사용하세요.
sglang.profiler CLI 파라미터:
| 파라미터 | 설명 |
|---|---|
--url |
SGLang 서버 주소 |
--output-dir |
출력 디렉토리 (기본값 SGLANG\_TORCH\_PROFILER\_DIR) |
--num-steps |
프로파일링할 스텝 수 |
--profile-by-stage |
prefill / decode 단계를 별도로 프로파일링 |
--profile-prefix |
트레이스 파일명 접두사 |
--cpu / --gpu / --mem / --rpd |
수집할 액티비티 유형 |
3. 전체 파라미터 참조 (Full Parameter Reference)
모든 방법은 결국 서버에 /start_profile 요청을 보내요. 지원되는 전체 파라미터:
| 파라미터 | 설명 | 기본값 |
|---|---|---|
output\_dir |
출력 디렉토리. SGLANG\_TORCH\_PROFILER\_DIR 또는 /tmp로 폴백 |
/tmp |
num\_steps |
스텝 수. 설정하면 프로파일링이 자동 종료 — /stop_profile 불필요 | None |
start\_step |
프로파일링을 시작할 스텝 인덱스(포함), 워밍업 건너뛰기용 | 0 |
activities |
액티비티 유형: CPU, GPU, MEM, RPD. Ascend NPU에서는 CPU와 GPU만 지원. MEM은 CUDA 메모리 API에 의존해 조용히 무시됨. RPD는 ROCm을 요구해 오류를 발생시킴 | ["CPU", "GPU"] |
profile\_by\_stage |
prefill과 decode 단계를 별도로 프로파일링 | false |
with\_stack |
Python 호출 스택 기록. SGLANG\_PROFILE\_WITH\_STACK으로도 제어 가능 |
true |
record\_shapes |
연산자 입력 형태 기록. SGLANG\_PROFILE\_RECORD\_SHAPES으로도 제어 가능 |
true |
profile\_prefix |
트레이스 파일명 접두사 | None |
profile\_stages |
프로파일링할 단계, 예: ["prefill", "decode"]. profile\_by\_stage 필요 |
None |
4. 출력 파일 찾기 (Finding Output Files)
서버 로그가 트레이스 저장 위치를 명시적으로 알려줘요. 다음으로 찾을 수 있어요:
- 프로파일링 시작 시: 서버 로그가
Profiling starts. Traces will be saved to: <path> (with profile id: <id>)출력
[2026-05-19 13:23:15] Profiling starts. Traces will be saved to: /tmp/1779196995.6948605 (with profile id: 1779196995.6979997)
[2026-05-19 13:23:15] [WARNING] [350443] profiler.py: Invalid parameter export_type: None, reset it to text.
[2026-05-19 13:23:15] INFO: 127.0.0.1:40714 - "POST /start_profile HTTP/1.1" 200 OK
- 프로파일링 종료 시: 서버 로그가
Profiling done. Traces are saved to: <path>출력
[2026-05-19 13:23:17] Stop profiling...
[2026-05-19 13:23:17] [WARNING] [350443] profiler.py: Incorrect schedule: Stop profiler while current state is RECORD which may result in incomplete parsed data.
[rank0]:[W519 13:23:17.084812760 compiler_depend.ts:3136] Warning: The indexFromRank 0 is not equal indexFromCurDevice 4 , which might be normal if the number of devices on your collective communication server is inconsistent.Otherwise, you need to check if the current device is correct when calling the interface.If it's incorrect, it might have introduced an error. (function operator())
[2026-05-19 13:23:17] [INFO] [352725] profiler.py: Start parsing profiling data: /tmp/1779196995.6948605/localhost.localdomain_350443_20260519132315700_ascend_pt
[2026-05-19 13:23:22] [INFO] [352734] profiler.py: CANN profiling data parsed in a total time of 0:00:04.022310
[2026-05-19 13:23:32] [INFO] [352725] profiler.py: All profiling data parsed in a total time of 0:00:14.305669
[2026-05-19 13:23:32] Profiling done. Traces are saved to: /tmp/1779196995.6948605
- CLI 출력:
sglang.profiler가Dump profiling traces to <path>출력
Dump profiling traces to /tmp/1779243331.3219
Waiting for 10 steps and the trace to be flushed.... (profile_by_stage=False)
디렉토리 구조는 <output_dir>/<hostname>_<pid>_<timestamp>_ascend_pt/예요. 방법 C(bench_serving --profile)를 사용하면 타임스탬프 서브디렉토리가 추가돼요: <output_dir>/<timestamp>/<hostname>_<pid>_<timestamp>_ascend_pt/. 정확한 경로는 항상 서버 로그를 확인하세요: Profiling done. Traces are saved to: <path>.
5. 결과 보기 (Viewing Results)
프로파일링이 종료되면(/stop_profile 반환 또는 num_steps 자동 트리거) 서버가 원시 데이터를 자동으로 파싱해요. ASCEND_PROFILER_OUTPUT 디렉토리에 다음 시각화 파일이 직접 포함돼요 — analyse()를 수동으로 호출할 필요가 없어요:
| 파일 | 설명 |
|---|---|
trace\_view.json |
Chrome Tracing 형식. MindStudio Insight에서 열기 |
analysis.db |
데이터베이스 형식 성능 데이터 |
ascend\_pytorch\_profiler\_0.db |
데이터베이스 형식 성능 데이터 |
kernel\_details.csv |
커널 레벨 데이터 |
operator\_details.csv |
연산자 레벨 데이터 |
step\_trace\_time.csv |
스텝 트레이스 타이밍 데이터 |
trace_view.json은 Chrome 내장chrome://tracing이나 Perfetto UI로도 열 수 있어요.
다중 노드 배포에서는 각 노드가 자신의 트레이스 파일을 생성해요. 이를 하나의 통합 트레이스로 병합하려면
/start_profile요청에"merge_profiles": true를 설정하세요. 그러나 Ascend NPU에서는 병합 기능이*_ascend_pt형식을 완전히 지원하지 않아요 — 병합 결과가 불완전하거나 부정확할 수 있어요. 각 노드에서trace_view.json을 개별적으로 보는 것을 권장해요. 자세한 내용은 Benchmark and Profiling을 참고하세요.
6. 원시 데이터 재파싱 (Re-parsing Raw Data) (선택 사항)
다른 파라미터로 기존 데이터를 다시 파싱해야 하거나, 프로파일링이 중단되어 ASCEND_PROFILER_OUTPUT이 자동 생성되지 않았다면 torch_npu의 analyse() 도구를 사용하세요:
from torch_npu.profiler.profiler import analyse
analyse("./sglang_profile/<hostname>_*_ascend_pt/")
보통은
analyse()를 수동으로 실행할 필요가 없어요 — 서버가 이미 데이터를 자동으로 파싱해요. 재파싱이나 중단된 데이터 처리에만 사용하세요.ASCEND_PROFILER_OUTPUT이 이미 존재하는 상태에서analyse()를 실행하면 원래 디렉토리를 덮어써요. 원래 데이터가 필요하면analyse()실행 전에 백업하세요.
모범 사례 (Best Practices)
공통 참고 사항 (Common Notes)
- 출력 찾기: 서버 로그에서
Profiling starts. Traces will be saved to: <path>와Profiling done. Traces are saved to: <path>, 또는sglang.profiler출력의Dump profiling traces to <path>를 확인하세요. - 트레이스 파일 크기 제어:
--num-prompts와--random-output-len으로 요청 수와 출력 길이를 줄여 브라우저에서 열기 어려운 큰 트레이스 파일을 피하세요. - 워밍업 반복:
start_step을 설정해 처음 몇 개의 워밍업 스텝을 건너뛰고 정상 상태에서 성능 데이터를 캡처하세요. - 프로파일링 스텝 수:
num_steps나--profile-steps의 큰 값은 길어진 프로파일링 데이터 파싱 시간을 초래할 수 있어요. 빠른 개요만 필요하면 이 값을 적절히 줄이세요. - CUDA Graph 영향: 트레이스에서 Python 호출 스택 → 연산자 매핑 전체를 보려면 서버 시작 시
--disable-cuda-graph를 추가하세요. 이는 decode 성능을 떨어뜨리므로 프로파일링 중에만 사용하세요. CUDA Graph 캡처를 구체적으로 분석하려면--enable-profile-cuda-graph를 사용하세요 — 트레이스는SGLANG_TORCH_PROFILER_DIR/graph_capture_profile/에 저장돼요. - 다중 노드 배포: 다중 노드 환경에서는 성능 데이터가 노드들에 분산돼요. Ascend NPU에서
merge_profiles기능은 지원이 제한적이에요 — 각 노드에서 개별적으로*_ascend_pt/ASCEND_PROFILER_OUTPUT/trace_view.json을 확인하세요. PD 분리 모드에서는 prefill과 decode 워커를 별도로 프로파일링해야 해요 — Profile In PD Disaggregation Mode 참고.
같이 보기 (See Also)
- SGLang Benchmark and Profiling — 일반 SGLang 프로파일링 가이드
- Ascend NPU 퀵스타트 — Ascend NPU 환경 설정
- Ascend NPU 최적화 — Ascend NPU 최적화 파라미터
- Ascend NPU 성능 테스트 — Ascend NPU 성능 벤치마킹
- Ascend NPU 환경 변수 — 환경 변수 참조