This document is relevant for: Trn2, Trn3
How to profile vLLM Neuron workloads#
Task overview#
This guide explains how to capture Neuron Runtime (NRT) profiles on a
live vLLM serving instance using the /start_profile and
/stop_profile HTTP endpoints. Profiles can be viewed in Neuron
Explorer for device-level performance analysis.
Prerequisites#
A running vLLM server on a Neuron instance (Trn2 or Inf2)
The
neuron-explorertool for viewing.ntfffilescurlor equivalent HTTP client
Architecture#
For the full profiler architecture and NRT API design, see Neuron profiling design.
Instructions#
1. Start the server with profiling enabled#
Enable the profiler at server startup. We reuse "cuda" as the
profiler kind to mount the HTTP endpoints:
vllm serve openai/gpt-oss-20b \
--tensor-parallel-size 8 \
--profiler-config '{"profiler": "cuda"}' \
--additional-config '{
"neuron_profiler": {
"activities": ["device_profile", "system_profile"],
"neuron_cores": [0, 1, 2, 3],
"output_dir": "/tmp/nrt_profile"
}
}'
2. Start profiling#
Once the server is ready and handling requests:
curl -X POST http://localhost:8000/start_profile
3. Send representative workload#
Send requests that represent your production traffic pattern:
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-oss-20b",
"prompt": "Explain quantum computing in simple terms.",
"max_tokens": 200
}'
4. Stop profiling#
curl -X POST http://localhost:8000/stop_profile
5. View profiles in Neuron Explorer#
Open the .ntff files in Neuron Explorer:
neuron-explorer view -d /tmp/nrt_profile/
Configuration reference#
Profiler config (via --profiler-config)#
Field |
Type |
Default |
Description |
|---|---|---|---|
|
str |
— |
Must be |
|
int |
0 |
Skip N engine steps before starting |
|
int |
— |
Auto-stop after N engine steps |
Neuron profiler config (via --additional-config)#
Nested under "neuron_profiler":
Field |
Type |
Default |
Description |
|---|---|---|---|
|
list[str] |
|
Activity types to capture |
|
list[int] or null |
null (rank 0) |
Which worker ranks to profile |
|
str |
|
Output directory for profile data |
|
int or null |
null (NRT default) |
Max system trace events per NC |
Valid activities values: "system_profile", "device_profile",
"host_memory", "cpu_util", "all".
Iteration control#
One iteration equals one execute_model call (one batched forward
pass). The state machine in WorkerProfiler.step() handles
delay/max iteration logic:
Config field |
Behavior |
|---|---|
|
Skip N steps before calling NRT begin |
|
Auto-call NRT stop after N steps |
Example — profile steady-state only (skip warmup):
vllm serve <model> \
--profiler-config \
'{"profiler": "cuda", "delay_iterations": 50, "max_iterations": 20}' \
--additional-config \
'{"neuron_profiler": {"output_dir": "/tmp/nrt_profile"}}'
curl -X POST http://localhost:8000/start_profile
# Auto-starts after 50 iterations, auto-stops after 20 more
Profiling with vllm bench#
For quick benchmarking with profiling:
vllm bench serve \
--backend vllm \
--model openai/gpt-oss-20b \
--dataset-name sharegpt \
--dataset-path sharegpt.json \
--profile \
--num-prompts 5
Disaggregated inference profiling#
In a disaggregated inference setup, prefill and decode run as separate
vLLM server instances. Each instance has its own /start_profile and
/stop_profile endpoints.
Proxy server pass-through#
The DI proxy server forwards profile requests to all backend servers:
Client Proxy Prefill Server Decode Server
│ │ │ │
├─ POST /start_profile ──→│ │ │
│ ├─ POST /start_profile ──→│ │
│ ├─ POST /start_profile ──────────────────→│
│ │ │ │
│ (200 OK after all backends respond) │ │
│←────────────────────────┤ │ │
│ │ │ │
│ ... requests profiled on both servers ... │ │
│ │ │ │
├─ POST /stop_profile ───→│ │ │
│ ├─ POST /stop_profile ───→│ │
│ ├─ POST /stop_profile ────────────────────→│
│ │ │ │
│←────────────────────────┤ │ │
For deployments without a proxy, manually hit the endpoints on each server you want to profile.
Profile output structure#
After /stop_profile, the output directory contains:
output_dir/
i-<instance_id>_pid_<pid>/<timestamp>/
profile_nc_0_session_0.ntff # Device profile (NTFF)
ntrace.pb # System trace
trace_info.pb # Trace metadata
cpu_util.pb # CPU utilization (if enabled)
host_mem.pb # Host memory (if enabled)
neffs/
graph_<hash1>.neff # Compiled NEFFs
graph_<hash2>.neff
NTFF files are viewed with Neuron Explorer. NEFFs are automatically copied from the compile cache — they are required for Neuron Explorer to render device profiles and correlate with instruction data.
Confirm your work#
After stopping a profile, verify output was generated:
ls /tmp/nrt_profile/
# Should show i-<instance>_pid_<pid>/ directory with .ntff files
Open in Neuron Explorer to verify traces were captured correctly.
Common issues#
No profile output generated#
Possible solution: Ensure
--profiler-config '{"profiler": "cuda"}'was passed at server startup. The endpoints are only mounted when this flag is set.
Empty or truncated system traces#
Possible solution: Increase
sys_trace_max_events_per_ncin the neuron profiler config. The default ring buffer may overflow during long profiling sessions.
Neuron Explorer cannot render device profiles#
Possible solution: Ensure NEFFs are present in the
neffs/subdirectory of the output. They should be auto-copied from the compile cache. If missing, set the compile cache path viaNEURON_COMPILED_ARTIFACTS.
Profile shows no activity#
Possible solution: Ensure requests were being processed between
/start_profileand/stop_profile. If usingdelay_iterations, verify enough iterations elapsed before profiling began.