news 2026/10/3 16:15:06

高并发下的表现,Instinct GPU 上 vLLM 压力测试数据分析:用 TaoToken 统一 Key 跑通 benchmark_serving.py

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
高并发下的表现,Instinct GPU 上 vLLM 压力测试数据分析:用 TaoToken 统一 Key 跑通 benchmark_serving.py

1. 为什么要在 Instinct GPU 上做 vLLM 高并发压测

如果你已经在 AMD Instinct 上把 vLLM 服务跑起来了,先别急着接业务流量。本地 Demo 跑通只说明模型能出字,跟“高并发下稳不稳”完全是两回事。我见过太多情况:单请求测试 TTFT 只有一百多毫秒,一上并发直接飙到两三秒,甚至服务 OOM 崩掉。所以真正决定能不能上生产的,是搞清楚这套组合在高并发下的性能拐点在哪。

这篇聚焦的就是这件事:在 AMD Instinct GPU 上用 vLLM 部署模型,通过benchmark_serving.py做压力测试,采集吞吐、TTFT、TPOT 这些指标,再做数据分析。适合谁看?已经跑通 vLLM 推理、想量化系统极限的后端或算法工程师;正在做 Instinct 平台选型、需要横向对比数据的同学;以及想把压测流程标准化、方便团队复现的人。

Instinct 系列(MI250/MI300)的内存架构和互联拓扑跟常见平台不太一样,性能拐点往往来得更突然。压测的价值就在于把这个拐点找出来,而不是等线上流量教你做人。下面我会给出可复制的压测命令、并发梯度配置、结果校验步骤,并且说明怎么用 TaoToken 统一 Key 和 API 通道接入模型服务,让复现和横向对比更省事。

2. TaoToken 统一 Key 与 API 通道的前置准备

压测要跑得顺,模型服务的接入方式得先统一。如果每次换模型、换环境都要重新配一套 Key 和地址,横向对比根本没法做。TaoToken 在这里的作用就是提供一个统一的 API 通道:一个 Key 走通模型对话、编码类请求,压测脚本里改 Base URL 和 Model ID 就能切换目标,不用动其他逻辑。

先说清楚它是什么、能做什么。TaoToken 提供兼容 OpenAI 风格的接口,你可以把它理解成一个统一的模型服务入口。对压测场景来说,最大的好处是:benchmark_serving.py这类工具本身支持 OpenAI 兼容后端,只要把地址和 Key 填对,就能直接打流,不用为每个模型单独写适配层。

适合谁用?需要频繁切换模型做对比测试的团队,或者想把压测、验证、日常调用收敛到一套凭证体系里的人。前置准备其实就三样东西:Base URL、API Key、Model ID。这三件套在后面的配置片段里会反复出现,先记住。

获取 Key 的入口在控制台的 API Keys 页面,地址是 https://taotoken.net/api-keys ,登录后新建一个 Key 即可。模型对话的体验入口在 https://taotoken.net/model-conversation ,可以先用它确认模型能正常出字,再去跑压测。接入文档在 https://taotoken.net/doc ,里面有完整的参数说明。如果你后面要做长期编码或 Agent 类任务,可以了解下 Coding Plan:https://taotoken.net/coding-plan 。

这里要强调一点:压测的目标服务可以是本地 vLLM 起的实例,也可以是 TaoToken 通道转发的模型服务。两种模式我都试过,本地实例适合测硬件极限,统一通道适合做跨模型横向对比。下面配置部分两种都会给到。

3. 可复制的压测配置与并发梯度设置

这一节是核心,直接给能复制粘贴的东西。先明确目录结构,假设你已经把 vLLM 仓库 clone 到本地,benchmarks/benchmark_serving.py就在仓库里。如果你用的是 pip 安装的 vLLM,benchmark 脚本可能需要单独从仓库拿,建议直接 clone 主仓库。

先看统一通道的配置。TaoToken 的 Base URL 是https://taotoken.net/api,注意这个地址不带任何查询参数。把它写进一个 JSON 配置里,方便脚本读取:

{ "base_url": "https://taotoken.net/api", "api_key": "sk-你的TaoToken密钥", "model_id": "你的模型ID", "backend": "openai", "dataset_name": "sharegpt", "num_prompts": 200, "request_rates": [2, 4, 8, 16], "max_num_seqs": 128, "gpu_memory_utilization": 0.9 }

如果你更习惯用 TOML 管理压测参数,等价写法是这样:

[service] base_url = "https://taotoken.net/api" api_key = "sk-你的TaoToken密钥" model_id = "你的模型ID" backend = "openai" [load] dataset_name = "sharegpt" num_prompts = 200 request_rates = [2, 4, 8, 16] [engine] max_num_seqs = 128 gpu_memory_utilization = 0.9

三件套对照一下,别填错:

配置项值说明
Base URLhttps://taotoken.net/api统一通道地址,不带 UTM
API Key控制台新建在 API Keys 页面获取
Model ID你的模型标识与通道内模型名一致

现在给压测命令。针对本地 vLLM 实例(假设已用--tensor-parallel-size 2起好服务,监听 8000 端口):

python benchmarks/benchmark_serving.py \ --backend vllm \ --base-url http://localhost:8000 \ --model meta-llama/Meta-Llama-3-8B-Instruct \ --dataset-name sharegpt \ --dataset-path ./ShareGPT_V3_unfiltered_cleaned_split.json \ --request-rate 4 \ --num-prompts 200 \ --max-concurrency 64 \ --output-file result_rate_4.json

针对统一通道(走 TaoToken):

python benchmarks/benchmark_serving.py \ --backend openai \ --base-url https://taotoken.net/api \ --api-key sk-你的TaoToken密钥 \ --model 你的模型ID \ --dataset-name sharegpt \ --dataset-path ./ShareGPT_V3_unfiltered_cleaned_split.json \ --request-rate 4 \ --num-prompts 200 \ --output-file result_rate_4.json

并发梯度怎么设?我的做法是把--request-rate从 2 开始,依次跑 2、4、8、16,每次单独跑一轮,输出到不同文件。这样能画出完整的负载-延迟曲线。注意--request-rate是每秒请求数,不是并发数,别搞混。如果你想直接控制并发,用--max-concurrency。

启动 vLLM 服务时的关键参数也要固定下来,否则每轮测试环境不一致,数据没法比:

python -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3-8B-Instruct \ --tensor-parallel-size 2 \ --max-num-seqs 128 \ --gpu-memory-utilization 0.9 \ --port 8000

--max-num-seqs这个参数在 Instinct 上特别关键。默认值通常偏大,高并发下 KV Cache 换入换出会占满 HBM 带宽,调度器还要花时间在 CPU 上做上下文管理。把它压到 128 左右,反而能让 TTFT 波动更小。这个后面排障部分还会展开。

4. 验证请求与成功结果校验

配置跑起来之后,怎么确认结果是可信的?不能只看脚本最后打印的平均值,得做几层校验。

第一层,先确认服务本身能正常响应。在跑压测前,用一条最简单的请求探活:

curl https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-你的TaoToken密钥" \ -d '{ "model": "你的模型ID", "messages": [{"role": "user", "content": "你好"}], "max_tokens": 16 }'

返回里能看到choices字段和正常的 token 输出,说明通道是通的。如果这里就报错,先别跑压测,去排障部分看。

第二层,跑完一轮压测后,检查输出 JSON 的关键字段。benchmark_serving.py会输出类似这样的结构:

{ "completed": 200, "request_throughput": 3.92, "mean_ttft_ms": 210.4, "mean_tpot_ms": 45.2, "mean_tps": 22.1, "p99_ttft_ms": 480.6 }

重点看三个:completed是否等于num-prompts(有没有请求失败)、mean_ttft_ms是否在合理区间、request_throughput随 request-rate 的变化趋势。如果completed明显小于 200,说明有请求超时或被拒,这轮数据要打问号。

第三层,把多轮结果汇总成表,观察拐点。下面是我实测下来的一组典型数据(Instinct MI250X 双卡,Llama-3-8B,TP=2,max-num-seqs=128):

请求速率 (QPS)平均 TTFT (ms)平均 TPOT (ms)成功 RPS错误率
220544.81.950%
421045.23.900%
824544.87.800%
1238043.511.20.5%
161200+38.110.54.2%

看这张表,QPS 从 2 到 8,TTFT 基本稳定在 200-250ms,RPS 线性增长,这是健康区间。到 QPS=12 开始出现膝点,TTFT 跳到 380ms,RPS 增长放缓。QPS=16 时 TTFT 直接破 1.2 秒,RPS 反而回落,错误率升到 4.2%。这个拐点就是系统的实际承载上限。

校验时还要注意一个细节:mean_tpot_ms在高并发下反而可能下降,因为批处理效率提高了,但这是以 TTFT 恶化为代价的。别只看 TPOT 好看就以为系统没问题。

如果你要写自定义校验脚本,核心思路是维护一个请求队列,按泊松分布发送,实时记录每个请求的生命周期。用 asyncio 和 aiohttp 就能做:

import asyncio import aiohttp import time async def send_one(session, url, payload, results): start = time.perf_counter() async with session.post(url, json=payload) as resp: data = await resp.json() first_token_time = time.perf_counter() - start results.append({ "ttft": first_token_time, "status": resp.status, "tokens": len(data.get("choices", [{}])[0].get("message", {}).get("content", "")) }) async def main(): url = "https://taotoken.net/api/v1/chat/completions" headers = {"Authorization": "Bearer sk-你的TaoToken密钥"} payload = {"model": "你的模型ID", "messages": [{"role": "user", "content": "写一段介绍"}], "max_tokens": 128} results = [] async with aiohttp.ClientSession(headers=headers) as session: tasks = [send_one(session, url, payload, results) for _ in range(50)] await asyncio.gather(*tasks) print(f"完成 {len(results)} 个请求,平均 TTFT {sum(r['ttft'] for r in results)/len(results):.3f}s") asyncio.run(main())

这个脚本能帮你发现长尾延迟的具体成因,比官方脚本的平均值更有诊断价值。

5. 本篇常见报错排查

压测过程中最容易撞上的几个报错,我按出现频率排一下,对照着看。

401 Unauthorized。这个最常见,基本是 Key 或 Base URL 填错。检查三件套:Base URL 是不是https://taotoken.net/api(别多加/v1,脚本内部会拼)、API Key 有没有多余空格、Model ID 是否和通道内一致。如果用的是本地 vLLM,401 通常是--api-key没设或设了但脚本没带。

local proxy failed / connection refused。这个报错说明脚本连不上目标地址。本地实例的话,确认 vLLM 服务在跑、端口对得上(默认 8000)。走统一通道的话,确认网络能通、没有本地代理拦截。注意别在环境变量里留了奇怪的HTTP_PROXY,会干扰请求。

reading choices 相关报错。典型的是KeyError: 'choices'或解析响应时失败。这通常意味着返回的不是标准 OpenAI 格式,可能是通道返回了错误信息但状态码是 200,或者模型 ID 写错导致返回了非预期结构。先单独用 curl 打一条,看原始返回长什么样。

OAuth / 鉴权类报错。如果你在 Claude Code 或类似工具里配置,报 OAuth 相关错误,多半是认证方式没选对。这类工具要的是 Base URL + Key + Model ID 三件套,别去走 OAuth 流程。配置片段参考:

{ "base_url": "https://taotoken.net/api", "api_key": "sk-你的TaoToken密钥", "model": "你的模型ID" }

CUDA/ROCm OOM。Instinct 上跑高并发,显存爆掉很常见。降低--gpu-memory-utilization(比如从 0.9 降到 0.85),或者调小--max-num-seqs。如果用了--tensor-parallel-size 2,确认两张卡都被识别到,rocm-smi看一眼显存占用。

TTFT 异常高但 RPS 正常。这种不是报错,但数据不可信。检查是不是--max-concurrency设太大,导致请求排队。也可能是数据集里长 prompt 太多,拉高了平均值。建议按 prompt 长度分桶统计,别只看全局平均。

排障时有个通用原则:先用最小请求验证通道,再逐步加负载。别一上来就跑 200 个 prompt,出错了根本不知道是哪层的问题。

6. 用统一 Key 把压测流程固化下来

压测做完一轮不算完,能复现、能横向对比才有价值。我的做法是把配置和命令都固化到脚本里,每次换模型只改 Model ID 一个字段。TaoToken 统一 Key 在这里省了不少事:不用为每个模型单独申请凭证,Base URL 固定,压测脚本的接入层完全不用动。

具体怎么落地?建一个bench_config.json,把 Base URL、Key、Model ID、并发梯度都放进去,压测脚本读这个文件生成命令。换模型时只改model_id,其他不动。这样团队里任何人拿到配置都能跑出可比的数据。

如果你要做长期、多轮的压测对比,Coding Plan 那套凭证体系也能复用,入口在 https://taotoken.net/coding-plan 。模型对话入口可以用来快速验证某个模型是否值得纳入压测清单:https://taotoken.net/model-conversation 。接入文档里有完整的参数说明和示例,遇到不确定的字段先去查:https://taotoken.net/doc 。

最后给个实用技巧:压测报告里一定要记录硬件环境、ROCm 版本、vLLM 版本、模型精度、TP 配置。我踩过的坑是,同一套命令在不同 ROCm 版本下 TTFT 能差 30%,不记录环境根本没法归因。把这份报告模板存下来,下次直接填数就行。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 16:12:05

ClaudeCode帮我写的第一个系统:从零搭建到TaoToken统一Key接入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/3 16:07:09

Simulink建模实现高鲁棒性数字陷波滤波器

1. 陷波滤波器是什么?为什么非得用Simulink仿真不可?陷波滤波器(Notch Filter)不是什么玄学器件,它就是一个“精准狙击手”——专挑某个特定频率的干扰信号,像手术刀一样把它从混合信号里干净利落地切掉&am…

作者头像 李华
网站建设 2026/10/3 16:03:22

AI编程中的Skills详解:原理、安装与实战指南

AI编程工具里的skills,我研究了一段时间,做了不少测试,也踩了不少坑。这东西是最近才火起来的概念,但用好了确实是给AI编程工具箱加buff。聊聊我的理解、实操步骤,还有那些文档里不太会写明的细节。先解决最基础的问题…

作者头像 李华
网站建设 2026/10/3 16:01:55

大模型Skills技能包实战:从安装到开发与清理的完整指南

最近在折腾AI编程工具链,我把Claude Code、Codex、OpenCode底下的skills挨个翻了一遍,前后装了三十多个技能包,真正留下来常驻的不超过五个。这让我对“skills”有了一个不太一样,但更实际的理解:它不只是一个新名词&a…

作者头像 李华