基准测试和性能分析#
基准测试#
在不使用服务器的情况下,运行单个静态批次的延迟基准测试。参数与
launch_server.py相同。 请注意,这是一个没有动态批处理服务器的简化测试脚本,因此对于真实服务器可以处理的批次大小,它可能会耗尽内存。真实服务器会将预填充分批处理,而此简化脚本则不会。不使用服务器(无需启动服务器)
python -m sglang.bench_one_batch --model-path meta-llama/Meta-Llama-3.1-8B-Instruct --batch 32 --input-len 256 --output-len 32
使用服务器(请先使用
sglang.launch_server启动服务器,然后运行以下命令)python -m sglang.bench_one_batch_server --base-url http://127.0.0.1:30000 --model-path meta-llama/Meta-Llama-3.1-8B-Instruct --batch-size 32 --input-len 256 --output-len 32
基准测试离线处理。此脚本将启动一个离线引擎并运行基准测试。
python3 -m sglang.bench_offline_throughput --model-path meta-llama/Meta-Llama-3.1-8B-Instruct --num-prompts 10
基准测试在线服务。请使用
sglang.launch_server启动服务器,然后运行以下命令。python3 -m sglang.bench_serving --backend sglang --num-prompt 10
使用 PyTorch Profiler 进行性能分析#
Pytorch Profiler 是一个方便的基础工具,用于检查内核执行时间、调用堆栈以及内核重叠和占用情况。
使用 sglang.bench_serving 对服务器进行性能分析#
# 设置追踪路径
export SGLANG_TORCH_PROFILER_DIR=/root/sglang/profile_log
# 启动服务器
python -m sglang.launch_server --model-path meta-llama/Llama-3.1-8B-Instruct
# 从客户端发送性能分析请求
python -m sglang.bench_serving --backend sglang --model meta-llama/Llama-3.1-8B-Instruct --num-prompts 10 --sharegpt-output-len 100 --profile
请确保在服务器和客户端都设置了 SGLANG_TORCH_PROFILER_DIR,否则无法正确生成追踪文件。一种安全的方法是在 shell 的 .*rc 文件(如 bash 的 ~/.bashrc)中设置 SGLANG_TORCH_PROFILER_DIR。
有关更多详细信息,请参阅 Bench Serving Guide。
在 PD 分离模式下进行性能分析#
在 PD 分离模式下进行性能分析时,由于 torch profiler 的限制,预填充和解码工作进程必须单独进行性能分析。bench_serving 命令为此提供了专门的选项:
对预填充工作进程进行性能分析#
# 设置追踪路径
export SGLANG_TORCH_PROFILER_DIR=/root/sglang/profile_log
# 启动预填充和解码服务器(设置方法参见 PD 分离文档)
python -m sglang.launch_server --model-path meta-llama/Llama-3.1-8B-Instruct --disaggregation-mode prefill
python -m sglang.launch_server --model-path meta-llama/Llama-3.1-8B-Instruct --disaggregation-mode decode --port 30001 --base-gpu-id 1
# 启动路由器
python -m sglang_router.launch_router --pd-disaggregation --prefill http://127.0.0.1:30000 --decode http://127.0.0.1:30001 --host 0.0.0.0 --port 8000
# 发送针对预填充工作进程的性能分析请求
python -m sglang.bench_serving --backend sglang --model meta-llama/Llama-3.1-8B-Instruct --num-prompts 10 --sharegpt-output-len 100 --profile --pd-separated --profile-prefill-url http://127.0.0.1:30000
对解码工作进程进行性能分析#
# 发送针对解码工作进程的性能分析请求
python -m sglang.bench_serving --backend sglang --model meta-llama/Llama-3.1-8B-Instruct --num-prompts 10 --sharegpt-output-len 100 --profile --pd-separated --profile-decode-url http://127.0.0.1:30001
重要说明#
--profile-prefill-url和--profile-decode-url是互斥的 - 您不能同时分析两者这两个选项都支持多实例设置下的多个工作进程 URL:
# 分析多个预填充工作进程 python -m sglang.bench_serving --backend sglang --model meta-llama/Llama-3.1-8B-Instruct --num-prompts 10 --profile --pd-separated --profile-prefill-url http://127.0.0.1:30000 http://127.0.0.1:30002 # 分析多个解码工作进程 python -m sglang.bench_serving --backend sglang --model meta-llama/Llama-3.1-8B-Instruct --num-prompts 10 --profile --pd-separated --profile-decode-url http://127.0.0.1:30001 http://127.0.0.1:30003
在启动服务器之前,确保在所有工作节点上设置了
SGLANG_TORCH_PROFILER_DIR有关设置 PD 分离的更多详细信息,请参阅 PD Disaggregation Guide
使用 sglang.bench_offline_throughput 对服务器进行性能分析#
export SGLANG_TORCH_PROFILER_DIR=/root/sglang/profile_log
# 使用 bench_one_batch.py 分析单个批次
# 批次大小可以通过 --batch 参数控制
python3 -m sglang.bench_one_batch --model-path meta-llama/Llama-3.1-8B-Instruct --batch 32 --input-len 1024 --output-len 10 --profile
# 使用 bench_offline_throughput.py 分析多个批次
python -m sglang.bench_offline_throughput --model-path meta-llama/Llama-3.1-8B-Instruct --dataset-name random --num-prompts 10 --profile --mem-frac=0.8
使用 sglang.profiler 对服务器进行性能分析#
当服务器正在运行时(例如,正在处理解码请求),您可以通过向服务器发送性能分析请求立即开始实时性能分析。
您可以通过运行 python3 -m sglang.profiler 来实现。例如:
# 终端 1: 发送生成请求
python3 -m sglang.test.send_one
# 终端 2: 在上述请求完成之前,在另一个终端中快速运行以下命令。
# 它将对上述请求的几个解码批次生成性能分析。
python3 -m sglang.profiler
您还可以将上述操作组合为单个命令
python3 -m sglang.test.send_one --profile
使用 HTTP API 端点对服务器进行性能分析#
SGLang 提供 HTTP API 端点来控制运行中服务器的性能分析。这允许您以编程方式启动和停止性能分析,这对于捕获特定工作负载模式很有用。
使用 /start_profile 端点#
/start_profile 端点在服务器上启动性能分析。您可以使用以下参数控制何时开始性能分析以及运行多长时间:
基本用法:
# 立即开始性能分析,进行 10 个步骤
curl -X POST http://127.0.0.1:30000/start_profile \
-H "Content-Type: application/json" \
-d '{
"num_steps": 10
}'
参数:
output_dir(可选):性能分析追踪文件将保存的目录。如果未指定,则使用SGLANG_TORCH_PROFILER_DIR环境变量,或默认使用/tmpnum_steps(可选):要性能分析的步骤数。如果未指定,性能分析将持续进行,直到使用/end_profile手动停止start_step(可选):开始性能分析的步骤编号(包含)。用于跳过预热迭代activities(可选):要性能分析的活动列表,例如["CPU", "GPU"]。默认为["CPU", "GPU"]merge_profiles(可选):是否合并分布式追踪。默认为false
关于步骤范围的说明: 性能分析从 start_step(包含)开始,持续 num_steps 次迭代。例如,使用 start_step=3 和 num_steps=10,性能分析将捕获步骤 3、4、5、6、7、8、9、10、11 和 12(总共 10 个步骤,从步骤 3 开始)。
使用 start_step 的高级用法:
# 等待 5 步(预热),然后进行 10 步性能分析
curl -X POST http://127.0.0.1:30000/start_profile \
-H "Content-Type: application/json" \
-d '{
"output_dir": "/tmp/profiles",
"start_step": 5,
"num_steps": 10,
"activities": ["CPU", "GPU"]
}'
连续性能分析(手动停止):
# 启动性能分析时不使用 num_steps - 必须使用 /end_profile 手动停止
curl -X POST http://127.0.0.1:30000/start_profile
使用 /end_profile 端点#
/end_profile 端点停止正在进行的性能分析会话并保存追踪文件。
# 停止性能分析并保存追踪
curl -X POST http://127.0.0.1:30000/end_profile
这仅在您启动性能分析时未指定 num_steps 才需要。如果指定了 num_steps,性能分析将在该步骤数后自动停止。
示例工作流#
# 终端 1: 启动服务器
export SGLANG_TORCH_PROFILER_DIR=/tmp/profiles
python -m sglang.launch_server --model-path meta-llama/Llama-3.1-8B-Instruct
# 终端 2: 启动连续性能分析
curl -X POST http://127.0.0.1:30000/start_profile \
-H "Content-Type: application/json" \
-d '{
"start_step": 3
}'
# 终端 3: 发送请求以生成负载
python -m sglang.bench_serving --backend sglang --num-prompts 100
# 终端 2: 完成后停止性能分析
curl -X POST http://127.0.0.1:30000/end_profile
用于分布式追踪的性能分析追踪合并器#
SGLang 现在支持自动合并来自具有多种并行类型(TP、DP、PP、EP)的分布式设置的性能分析追踪。此功能对于分析分布式运行中的性能特别有用。
多节点性能分析和共享存储注意事项#
单节点性能分析输出合并完全受支持。在跨多个节点的分布式环境中进行性能分析时,所有节点都应该能够访问输出目录的共享存储(例如 NFS、Lustre),以实现追踪文件的合并。
如果节点之间没有可访问的共享存储,目前不支持在性能分析期间自动合并追踪文件。
HTTP API 用法#
# 启用自动追踪合并的性能分析
curl -X POST <BASE_URL>/start_profile \
-H "Content-Type: application/json" \
-d '{
"output_dir": "/tmp/profiles", # 存储性能分析追踪的位置
"num_steps": 10,
"activities": ["CPU", "GPU"],
"merge_profiles": true # 可选参数,用于合并性能分析追踪(默认=False)
}'
命令行用法#
# 启用合并的性能分析
python -m sglang.profiler \
--num-steps 10 \
--cpu \
--gpu \
--output-dir /tmp/profiles \
--merge-profiles # 可选参数,用于合并性能分析追踪(默认=False)
输出文件#
性能分析合并器生成:
单个等级追踪文件:
{profile_id}-TP-{tp}-DP-{dp}-PP-{pp}-EP-{ep}.trace.json.gz合并的追踪文件:
merged-{profile_id}.trace.json.gz
可能的 PyTorch 错误#
如果在任何情况下遇到以下错误(例如,使用 qwen 2.5 VL):
RuntimeError: !stack.empty() INTERNAL ASSERT FAILED at "/pytorch/torch/csrc/autograd/profiler_python.cpp":983, please report a bug to PyTorch. Python replay stack is empty.
这可能是 PyTorch 错误,已在 Bug: vLLM Profiler 和 Bug: torch.profiler.profile 中报告。作为一种解决方案,您可以使用环境变量禁用 with_stack,如下所示:
export SGLANG_PROFILE_WITH_STACK=False
python -m sglang.bench_offline_throughput --model-path meta-llama/Llama-3.1-8B-Instruct --dataset-name random --num-prompts 10 --profile --mem-frac=0.8
查看追踪#
追踪文件可以从以下位置加载和可视化:
https://ui.perfetto.dev/(任何浏览器)
chrome://tracing(仅限 Chrome 浏览器)
如果浏览器由于追踪文件太大而无法打开, 客户端可以通过控制提示数量和提示输出长度生成小追踪文件(<100MB)。 例如,在性能分析服务器时,
python -m sglang.bench_serving --backend sglang --model meta-llama/Llama-3.1-8B-Instruct --num-prompts 2 --sharegpt-output-len 100 --profile
此命令使用 --num-prompts 参数将提示数量设置为 2,并使用 --sharegpt-output-len 参数将输出序列长度限制为 100,这样可以生成小追踪文件,浏览器可以流畅打开。
此外,如果您想通过 Trace 中的 CUDA 定位 SGLang Python 源代码,您需要在启动服务时禁用 CUDA Graph。这可以通过在启动服务的命令中使用 --disable-cuda-graph 参数来实现。
使用 Nsight 进行性能分析#
Nsight systems 是一个高级工具,它可以暴露更多性能分析细节,如寄存器和共享内存使用情况、带注释的代码区域以及低级 CUDA API 和事件。
先决条件:
使用 apt 安装,或在 NVIDIA Docker 容器 或 SGLang Docker 容器 中运行。
# 安装 nsys # https://docs.nvidia.com/nsight-systems/InstallationGuide/index.html 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
要对单个批次进行性能分析,请使用
nsys profile --trace-fork-before-exec=true --cuda-graph-trace=node python3 -m sglang.bench_one_batch --model meta-llama/Meta-Llama-3-8B --batch-size 64 --input-len 512
要对服务器进行性能分析,例如
# 启动服务器,根据需要设置延迟和持续时间时间 # 当持续时间用完后,服务器将被 nsys 杀死 nsys profile --trace-fork-before-exec=true --cuda-graph-trace=node -o sglang.out --delay 60 --duration 70 python3 -m sglang.launch_server --model-path meta-llama/Llama-3.1-8B-Instruct --disable-radix-cache # 客户端 python3 -m sglang.bench_serving --backend sglang --num-prompts 1000 --dataset-name random --random-input 1024 --random-output 512
实际上,我们建议用户将
--duration参数设置为一个较大的值。当用户想要服务器停止性能分析时,首先运行:nsys sessions list
以获取
profile-XXXXX形式的会话 ID,然后运行:nsys stop --session=profile-XXXXX
以手动杀死性能分析器并立即生成
nsys-rep文件。使用 NVTX 对代码区域进行注释,例如查看它们的执行时间。
# 安装 nvtx pip install nvtx
# 代码片段 import nvtx with nvtx.annotate("description", color="color"): # 一些关键代码
使用 Nsight Systems 进行逐层 NVTX 性能分析#
SGLang 提供内置的逐层 NVTX 注释,可与 CUDA Profiler 结合使用,在 Nsight Systems 中进行详细的逐层性能分析。这对于识别层的性能瓶颈特别有用。
将 --enable-layerwise-nvtx-marker 与 Nsight Systems 和 /start_profile 一起使用#
--enable-layerwise-nvtx-marker 标志会自动向模型中的每一层添加 NVTX 标记。当与 Nsight Systems 性能分析结合使用时,这可以查看详细的逐层性能,特别强大。
方法 1:使用 /start_profile 和 CUDA_PROFILER(用于编程控制)
此方法允许您通过 HTTP API 精确控制何时启动/停止性能分析,而 Nsight Systems 正在运行。
在 Nsight Systems 下使用逐层 NVTX 启动服务器:
# 终端 1: 使用 nsys 和 capture-range 选项启动服务器 nsys profile --trace-fork-before-exec=true \ --cuda-graph-trace=node \ --capture-range=cudaProfilerApi \ --capture-range-end=stop \ -o layerwise_profile \ python -m sglang.launch_server \ --model-path meta-llama/Llama-3.1-8B-Instruct \ --enable-layerwise-nvtx-marker \ --disable-cuda-graph
注意:对于 CUDA 图捕获的内核启动,不会发出 NVTX 标记。使用
--disable-cuda-graph确保所有逐层 NVTX 标记在追踪中发出。在另一个终端中,通过
/start_profile控制使用CUDA_PROFILER活性的性能分析:# 终端 2: 等待服务器准备就绪,然后启动 CUDA 性能分析 # 等待 3 步进行预热,然后进行 10 步性能分析 curl -X POST http://127.0.0.1:30000/start_profile \ -H "Content-Type: application/json" \ -d '{ "start_step": 3, "num_steps": 10, "activities": ["CUDA_PROFILER"] }'
发送请求以生成负载:
# 终端 3: 生成工作负载 python -m sglang.bench_serving --backend sglang --num-prompts 100
性能分析将在 10 步后自动停止(由于
num_steps: 10)。如果您没有指定num_steps,则需要手动停止:# 终端 2: 仅在不指定 num_steps 时才需要 curl -X POST http://127.0.0.1:30000/end_profile
--capture-range=cudaProfilerApi选项告诉 Nsight Systems 仅在cudaProfilerStart()和cudaProfilerStop()调用之间(由/start_profile和/end_profile触发)捕获数据,从而减少开销和文件大小。start_step参数跳过前 3 步以避免捕获预热开销。
方法 2:更简单的不使用 /start_profile API 的方法
对于不需要精细控制性能分析启动/停止的更简单用例,您可以使用 Nsight Systems 捕获整个工作负载进行性能分析:
# 终端 1: 使用逐层 NVTX 启动服务器
# 注意:--disable-cuda-graph 确保发出所有 NVTX 标记
python -m sglang.launch_server \
--model-path meta-llama/Llama-3.1-8B-Instruct \
--enable-layerwise-nvtx-marker \
--disable-cuda-graph
# 终端 2: 对基准测试客户端进行性能分析
nsys profile --trace-fork-before-exec=true \
--cuda-graph-trace=node \
-o layerwise_profile \
python -m sglang.bench_serving --backend sglang --num-prompts 10
此方法对整个客户端执行进行性能分析,包括所有服务器交互。逐层 NVTX 标记将在 Nsight Systems 时间线中可见。
查看性能分析结果:
使用 Nsight Systems 打开生成的 .qdrep 文件:
nsys-ui layerwise_profile.qdrep
在 Nsight Systems GUI 中,您将看到:
NVTX 范围:每个层显示为时间线中的标记范围,标记元数据中有详细信息
CUDA 内核:所有 GPU 内核与层注释一起显示
层层次结构:完整的模块路径(例如
meta-llama/Meta-Llama-3.1-8B-Instruct.model.layers.0.self_attn.qkv_proj)有助于识别特定层。前缀使用来自--model-path的完整模型路径。张量形状:输入/输出维度和参数形状包含在 NVTX 标记数据中
逐层 NVTX 性能分析的好处:
细粒度可见性:准确查看哪些层花费最多时间
内存跟踪:识别具有大内存分配的层
瓶颈识别:快速定位低效操作
通信开销:在多 GPU 设置中,查看每层通信成本
开发调试:验证模型架构更改具有预期的性能影响
其他提示#
您可以通过仅提供 config.json 文件,使用虚拟权重对模型进行基准测试。这允许快速测试模型变体而无需训练。为此,请向上述命令添加
--load-format dummy,然后您只需要检查点文件夹中有正确的config.json。您可以使用
--json-model-override-args对具有修改配置的模型进行基准测试(例如,更少的层数)。例如,您可以使用以下命令对只有 2 层和 2 个 kv 头的模型进行基准测试:python -m sglang.bench_one_batch --model-path meta-llama/Meta-Llama-3.1-8B-Instruct --batch 32 --input-len 256 --output-len 32 --load-format dummy --json-model-override-args '{"num_hidden_layers": 1, "num_key_value_heads": 1}'
您可以使用
--python-backtrace=cuda查看 CUDA 内核的 Python 调用堆栈,如 PyTorch Profiler 所示。(注意:这可能导致基于 CUDA 事件计时的不准确的长时间内核运行)有关更多参数,请参阅 Nsight Systems User Guide。