
vLLM 参数扫描实战用 vllm bench sweep 完成配置调优与延迟-吞吐权衡探索【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllmvLLM 内置了vllm bench sweep参数扫描Parameter Sweeps工具集它能在多组服务器/压测配置上自动运行基准测试并把结果汇总为 CSV 与可视化曲线帮助你在上线前完成吞吐、延迟与 SLA 的权衡决策。本文基于 vLLM 仓库中 docs/benchmarking/sweeps.md 的官方文档结合 vllm/benchmarks/sweep/ 目录下的实际源码实现完整覆盖serve、serve_workload、startup、plot、plot_pareto五个子命令的用法、参数文件格式、结果目录结构与底层执行流程读完即可复制运行完整的调优实验。一、Parameter Sweeps 概览五个子命令与统一调度vllm bench sweep是运行多配置基准测试并对比结果的命令套件。它的五个子命令在 vllm/benchmarks/sweep/cli.py 中统一注册子命令作用实现文件serve启动vllm serve对每组服务器配置迭代执行vllm bench serveserve.pyserve_workload在serve基础上自动探索不同负载水平寻找延迟-吞吐权衡serve_workload.pystartup对多组参数组合运行vllm bench startup对比冷/热启动时间startup.pyplot从扫描结果绘制性能曲线plot.pyplot_pareto绘制帕累托前沿平衡单用户吞吐与单 GPU 吞吐plot_pareto.pyCLI 入口由 vllm/entrypoints/cli/benchmark/sweep.py 中的BenchmarkSweepSubcommand挂到vllm bench主命令下子命令通过 argparse 的set_defaults(dispatch_functionentrypoint)分发到各自的main函数。需要说明如果你只需要对单一服务器配置做压测可以单独使用vllm bench serve或参考社区维护的 GuideLLM官方文档中也给出了同样的提示它在数据集加载、请求格式与负载模式上更加灵活。vllm bench sweep的价值在于把“多配置 × 多负载 × 多次重复”这件事自动化并沉淀为可绘图的结构化结果。二、在线压测扫描vllm bench sweep serve2.1 基本用法四步走运行serve扫描的步骤如下与 docs/benchmarking/sweeps.md 一致构造vllm serve基础命令传给--serve-cmd构造vllm bench serve基础命令传给--bench-cmd可选若要改变vllm serve的设置创建 JSON 参数组合文件路径传给--serve-params可选若要改变vllm bench serve的设置创建 JSON 参数组合文件路径传给--bench-params设置--output-dir并可选设置--experiment-name控制结果保存位置。示例 1扫描--max-num-seqs与--max-num-batched-tokens的组合写入benchmarks/serve_hparams.json[ { max_num_seqs: 32, max_num_batched_tokens: 1024 }, { max_num_seqs: 64, max_num_batched_tokens: 1024 }, { max_num_seqs: 64, max_num_batched_tokens: 2048 }, { max_num_seqs: 128, max_num_batched_tokens: 2048 }, { max_num_seqs: 128, max_num_batched_tokens: 4096 }, { max_num_seqs: 256, max_num_batched_tokens: 4096 } ]示例 2扫描 random 数据集的不同输入/输出长度写入benchmarks/bench_hparams.json[ { _benchmark_name: scenario_A, random_input_len: 128, random_output_len: 32 }, { _benchmark_name: scenario_B, random_input_len: 256, random_output_len: 64 }, { _benchmark_name: scenario_C, random_input_len: 512, random_output_len: 128 } ]完整命令示例vllm bench sweep serve \ --serve-cmd vllm serve meta-llama/Llama-2-7b-chat-hf \ --bench-cmd vllm bench serve --model meta-llama/Llama-2-7b-chat-hf --backend vllm --endpoint /v1/completions --dataset-name sharegpt --dataset-path benchmarks/ShareGPT_V3_unfiltered_cleaned_split.json \ --serve-params benchmarks/serve_hparams.json \ --bench-params benchmarks/bench_hparams.json \ --output-dir benchmarks/results \ --experiment-name demo默认情况下每个参数组合会压测3 次以提高结果可靠性源码中--num-runs默认值确为 3见 serve.py可用--num-runs调整且必须至少为 1否则在SweepServeArgs.from_cli_args中直接抛出ValueError。2.2 参数文件格式列表或字典两种写法参数文件的解析实现在 vllm/benchmarks/sweep/param_sweep.py 的ParameterSweep.read_json中列表格式每个元素是一个 dict代表一组参数组合上文两个示例都是这种格式字典格式键为基准名、值为参数字典见read_from_dict加载时自动转换为{_benchmark_name: name, **params}的记录适合给组合起语义化名字_benchmark_name字段不是 CLI 参数仅用于命名若提供了多个_benchmark_name源码会校验其唯一性重复直接报错。对于变量较多的参数组合官方文档建议设置_benchmark_name提供人类可读的名字当组合参数很多、生成的文件路径可能超过文件系统最大路径长度时该字段实际上是必需的。2.3 参数如何被注入到命令中apply_to_cmdParameterSweepItem继承自 dict其apply_to_cmd方法param_sweep.py描述了参数覆盖的完整规则理解它能帮你正确编写参数文件优先替换已有参数如果基础命令--serve-cmd/--bench-cmd中已存在同名参数则原地替换其值避免重复追加不存在则追加否则作为新的--key value追加到命令末尾键名归一化JSON 中优先用下划线max_num_seqsCLI 中优先用连字符--max-num-seqs_iter_param_key_candidates/_iter_cmd_key_candidates会在两种写法之间互相探测布尔值非嵌套布尔参数true变成--flag、false变成--no-flag带.的嵌套布尔参数则使用--keytrue/false形式dict 值会被序列化为 JSON 字符串传入适合一些复杂配置项带.的嵌套键如config.xxx这类内层配置参数按前缀逐段归一化不被 CLI 转换影响。serve主流程run_combsserve.py的循环结构是外层遍历serve_params为每组服务器参数只启动一次服务器内层遍历bench_params在同一台服务器上依次压测多个基准配置。每组基准跑完后调用server.after_bench()——默认调用全部/reset_*_cache端点清空前缀缓存等状态为下一次运行提供“干净起点”。如果你使用了自定义--serve-cmd可以通过--after-bench-cmd覆盖这个重置行为。重要机制提示官方文档以 important 标注同时传入--serve-params和--bench-params时脚本遍历二者的笛卡尔积可用--dry-run预览将要执行的全部命令而不实际运行每组--serve-params只启动一次服务器并让它存活以支撑多个--bench-params的运行。2.4serve子命令完整参数表以下参数、默认值均取自 serve.py 的add_cli_args参数默认值说明--serve-cmd必填启动服务器的命令vllm serve ...--bench-cmd必填压测命令vllm bench serve ...--after-bench-cmd无每次基准运行完成后调用该命令替代默认的缓存重置clear_cache()--show-stdout关打印子命令的标准输出调试时有用但较吵--server-ready-timeout300等待服务器就绪的超时时间秒--serve-params无vllm serve参数组合 JSON 文件列表或字典--bench-params无vllm bench serve参数组合 JSON 文件列表或字典--link-vars空serve 与 bench 之间的联动变量如max_num_seqsmax_concurrency,max_model_lenrandom_input_len-o,--output-dirresults结果根目录-e,--experiment-name当前时间戳实验名结果存于output_dir/experiment_name--num-runs3每个参数组合的运行次数--dry-run关仅打印命令不执行--resume关从上次中断处继续只运行尚无输出文件的参数组合其中--link-vars值得单独说明它声明 serve 侧与 bench 侧必须相等的变量对_comb_is_validserve.py会检查每个serve 组合, bench 组合对两侧任一变量缺失或值不相等的组合会被静默跳过。典型用途是把服务端的max_num_seqs与压测的max_concurrency绑定或把max_model_len与random_input_len绑定避免压测出非法配置。结果文件的断点续跑能力来自对输出路径的存在性检查run_benchmark发现runN.json已存在时直接跳过打印[SKIPPED BENCHMARK]而server_ctx在某个 serve 组合下所有 bench 组合的summary.json都已存在时连服务器都不启动_comb_needs_server返回 False使用空上下文。这也是--resume在意外中断例如连接 HF Hub 超时后能“继续扫描”的原理官方文档提示遇到此类错误时可以使用--resume。另注意不带--resume时如果实验目录已存在会直接报错“Cannot overwrite existing experiment_dir”防止误覆盖历史结果。三、负载探索器vllm bench sweep serve_workloadserve_workload是serve的变体源码上SweepServeWorkloadArgs直接继承SweepServeArgs它自动探索不同负载水平用来定位延迟与吞吐的权衡点结果同样可以用 第四节 的plot命令可视化从而判断哪些配置能满足可行的 SLA。负载可用请求速率或并发数表达用--workload-var选择取值request_rate或max_concurrency默认request_rate。命令示例vllm bench sweep serve_workload \ --serve-cmd vllm serve meta-llama/Llama-2-7b-chat-hf \ --bench-cmd vllm bench serve --model meta-llama/Llama-2-7b-chat-hf --backend vllm --endpoint /v1/completions --dataset-name sharegpt --dataset-path benchmarks/ShareGPT_V3_unfiltered_cleaned_split.json --num-prompts 100 \ --workload-var max_concurrency \ --serve-params benchmarks/serve_hparams.json \ --bench-params benchmarks/bench_hparams.json \ --num-runs 1 \ --output-dir benchmarks/results \ --experiment-name demo3.1 负载探索算法官方文档将算法概括为四步源码explore_comb_workloadsserve_workload.py与之逐条对应串行推理最低负载以max_concurrency1逐个发请求运行一次基准得到最低延迟与吞吐批量推理最高负载以max_concurrency数据集大小一次性发出所有请求运行一次基准得到最高延迟与吞吐估计第 2 步对应的workload_var数值在中间均匀取点用np.linspace(serial_value, batch_value, workload_iters)[1:-1]生成中间负载值去重取整后依次压测。第 3 步的估计逻辑在_estimate_workload_valueserve_workload.pyrequest_rate直接取结果中的request_throughput稳态下吞吐即请求到达率max_concurrency取request_throughput × mean_e2el_ms / 1000——这正是 Little 定律并发数 ≈ 吞吐 × 平均时延从批量运行的观测值反推出等效并发水平。数据集大小num_prompts的确定优先取bench_params组合中的num_prompts字段否则从--bench-cmd命令行中解析--num-prompts值两者都没有时使用 vllm/benchmarks/datasets 的DEFAULT_NUM_PROMPTS。3.2 两个专属参数参数默认值说明--workload-varrequest_rate每次迭代调整的变量可选request_rate/max_concurrency--workload-iters10要探索的负载级别数包含用于插值的前两次迭代源码强制至少为 2官方文档给出的经验提示值得照做--workload-var max_concurrency通常产生更可靠的结果因为它直接控制施加到 vLLM 引擎上的负载但为与 GuideLLM 的行为保持一致默认仍是--workload-var request_rate。这个子命令在功能上对应 GuideLLM 的--profile sweep模式。另外源码中有一处硬校验如果--bench-params的任何组合里已经手动设置了workload_varrequest_rate或max_concurrencyexplore_combs_workloads会直接抛错——该变量由探索器自动管理不允许外部覆盖。四、启动时间扫描vllm bench sweep startupstartup子命令对多组参数组合运行vllm bench startup用于比较不同引擎设置下的冷启动/热启动时间。运行步骤与 docs/benchmarking/sweeps.md 一致可选构造vllm bench startup基础命令传给--startup-cmd默认就是vllm bench startup可选复用serve扫描的--serve-paramsJSON 来变化引擎设置只有vllm bench startup支持的参数会被应用可选创建--startup-paramsJSON 来变化启动专属选项如迭代次数指定--output-dir保存结果。示例--serve-params变化并行规模[ { _benchmark_name: tp1, model: Qwen/Qwen3-0.6B, tensor_parallel_size: 1, gpu_memory_utilization: 0.9 }, { _benchmark_name: tp2, model: Qwen/Qwen3-0.6B, tensor_parallel_size: 2, gpu_memory_utilization: 0.9 } ]示例--startup-params变化冷/热迭代次数[ { _benchmark_name: qwen3-0.6, num_iters_cold: 2, num_iters_warmup: 1, num_iters_warm: 2 } ]完整命令示例vllm bench sweep startup \ --startup-cmd vllm bench startup --model Qwen/Qwen3-0.6B \ --serve-params benchmarks/serve_hparams.json \ --startup-params benchmarks/startup_hparams.json \ --output-dir benchmarks/results \ --experiment-name demo重要提示--serve-params或--startup-params中不支持的参数默认只打警告并忽略用--strict-params可以在遇到未知键时快速失败。这个过滤逻辑由_get_supported_startup_keysstartup.py实现——它通过反射vllm bench startup的 argparse 参数表动态构建“支持键集合”因此即使vllm bench startup的参数集发生变化扫描器也能自动适配。与serve的差异点均已在源码确认--num-runs默认值为1而非 3启动时间测量本身已含冷/热多次迭代没有服务器进程管理每个组合通过subprocess.run独立执行--startup-cmd并用_apply_output_json强制追加--output-json path把每次运行结果落到指定 JSON 文件。参数组合的笛卡尔积逻辑与serve相同--dry-run/--resume/--show-stdout行为一致。五、结果目录结构如何组织与复用扫描产物从serve.py的路径函数_get_comb_base_path/_get_comb_run_pathserve.py可以看出统一的目录约定startup的SERVE-/STARTUP-前缀同理output_dir/experiment_name/ ├── SERVE-serve组合名/ │ ├── BENCH-bench组合名/ # serve_workload 下另有 WL-varvalue/ 一层 │ │ ├── run0.json # 每次运行bench 结果 serve/bench 覆盖参数 run_number │ │ ├── run1.json │ │ ├── run2.json │ │ └── summary.json # 该组合全部 run 的数组 │ └── BENCH-另一个组合/... └── summary.csv # 所有运行记录合并成的扁平表几个关键细节每个runN.json是vllm bench serve --save-result的原始结果 JSON_update_run_data会在其中合并写入该组合的 serve/bench 覆盖参数与run_number因此单文件即可知道“这行数据是什么配置跑出来的”压测命令被固定追加--percentile-metrics ttft,tpot,itl,e2elserve.py保证结果里始终带有 TTFT/TPOT/ITL/E2EL 分位数指标供后续绘图使用summary.csv由 pandas 从所有 run 记录生成是plot与plot_pareto的数据基础。六、结果可视化vllm bench sweep plotplot从扫描结果目录读取全部 JSON绘制性能曲线。它接受一个位置参数EXPERIMENT_DIR并用以下分组变量组织图形实现见 plot.py--var-xx 轴默认total_token_throughput、--var-yy 轴默认median_ttft_ms--fig-by每个变量组合生成一张独立图--row-by/--col-by按变量拆行/拆列子图网格--curve-by按变量组合拆分曲线--filter-by逗号分隔的过滤语句支持、!、、、、六种运算符注意源码按长运算符优先匹配如max_concurrency1000,max_num_batched_tokens4096适合剔除离群点--bin-by分箱语句仅支持%运算符如request_throughput%1表示按 1 分箱避免过密的点--scale-x/--scale-y坐标轴刻度接受log、sqrt等字符串--fig-name默认FIGURE、--fig-dir相对实验目录、--fig-height默认 6.4 英寸、--fig-dpi默认 300、--no-error-bars默认显示误差棒因为每个组合有多次运行。官方文档给出的三个 Workload Explorer 结果绘图示例可直接复制EXPERIMENT_DIR${1:-benchmarks/results/demo} # Latency increases as the workload increases vllm bench sweep plot $EXPERIMENT_DIR \ --var-x max_concurrency \ --var-y median_ttft_ms \ --col-by _benchmark_name \ --curve-by max_num_seqs,max_num_batched_tokens \ --fig-name latency_curve # Throughput saturates as workload increases vllm bench sweep plot $EXPERIMENT_DIR \ --var-x max_concurrency \ --var-y total_token_throughput \ --col-by _benchmark_name \ --curve-by max_num_seqs,max_num_batched_tokens \ --fig-name throughput_curve # Tradeoff between latency and throughput vllm bench sweep plot $EXPERIMENT_DIR \ --var-x total_token_throughput \ --var-y median_ttft_ms \ --col-by _benchmark_name \ --curve-by max_num_seqs,max_num_batched_tokens \ --fig-name latency_throughput这三个图分别回答三类调优问题延迟随负载上升的曲线形态、吞吐随负载趋于饱和的位置、以及在“吞吐-延迟”平面上各配置的权衡曲线。--dry-run可以只打印将要绘制的图形信息而不真正出图适合先核对分组是否正确。七、帕累托前沿vllm bench sweep plot_paretoplot_pareto帮助你在单用户吞吐per-user与单 GPU 吞吐per-GPU之间做平衡选择。其动机是更高的并发/批大小能提升 GPU 利用率per-GPU 吞吐但会增加单用户延迟更低并发则相反帕累托前沿展示了所有运行中可达成的一对最好组合实现见 plot_pareto.py 的_pareto_frontier。坐标轴与输出的定义均已在源码中核实x 轴tokens/s/useroutput_throughput÷ 并发数。并发数优先取--user-count-var默认max_concurrency缺失时回退request_rate再回退观测峰值max_concurrent_requests见_infer_user_county 轴tokens/s/GPUoutput_throughput÷ GPU 数。GPU 数优先取--gpu-count-var如设置了否则从结果中推断为tensor_parallel_size × pipeline_parallel_size × data_parallel_size见_infer_gpu_count缺省各因子为 1输出单张图保存在OUTPUT_DIR/pareto/PARETO.png--label-by在每个数据点上标注所用配置默认max_concurrency,gpu_count。命令示例官方文档EXPERIMENT_DIR${1:-benchmarks/results/demo} vllm bench sweep plot_pareto $EXPERIMENT_DIR \ --label-by max_concurrency,tensor_parallel_size,pipeline_parallel_size同样支持--dry-run预览。注意该图要求结果中存在output_throughput字段否则_get_throughput会报错并列出可用的键名方便排查。八、小结与实操建议vllm bench sweep把“多配置压测”变成了可脚本化、可复现、可续跑的工程流程几个基于源码确认的实操要点先--dry-run后实跑所有子命令都支持先用它核对生成的完整命令序列笛卡尔积、link-vars 过滤、参数替换结果善用--resumeserve与startup均按“输出文件是否存在”做断点续跑长时间扫描中断后无需从头再来给复杂组合命名变量多时设置_benchmark_name且必须唯一既是可读性也是路径长度的保险负载探索优先用max_concurrency它直接约束引擎负载结果更稳定默认request_rate是为了对齐 GuideLLM 行为startup 扫描注意--strict-params默认静默丢弃不支持的参数只告警在自动化流水线中建议开启严格模式防止参数文件写错而无感知绘图先看summary.csvplot的全部过滤/分箱/分组能力都作用于这同一份数据先理解列名再调--filter-by/--curve-by效率最高。相关延伸阅读Benchmark CLI 文档 介绍vllm bench各基础命令优化配置文档 说明调优的一般方法实现代码集中在 vllm/benchmarks/sweep/含服务器进程管理 server.py 与文件名清洗 utils.py。【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考