
1. 为什么要在 AMD Instinct GPU 上做高并发推理压测如果你手里有一台搭载 AMD Instinct GPU 的推理服务器装好了 ROCm 和 vLLM服务也能正常跑起来那接下来最该问自己的问题不是“能不能跑”而是“能扛多少”。这就是高并发推理测试存在的意义。AMD Instinct GPU 在显存容量和带宽上很有优势比如 MI300X 级别的卡单卡就有 192GB HBM3跑 Llama 3 8B 甚至 70B 都不需要多卡切分。但显存大不等于并发能力强真正的瓶颈往往出现在连续批处理调度、KV Cache 管理和显存带宽搬运上。我这次测试的目标很明确用 vLLM 自带的 benchmark_serving.py在 AMD Instinct GPU ROCm 7.x 环境下从 1 到 64 并发梯度逐步加压找出吞吐量拐点同时观察首字延迟TTFT和每秒生成 Token 数TPS的变化曲线。测试模型选 Llama 3 8B Instruct数据集用 ShareGPT 子集因为它的对话长度分布更接近真实业务而不是那种每条都固定 512 token 的合成数据。为什么要结合 TaoToken 统一 API 接入因为实际生产里你不可能只跑一个模型。你可能同时要对比 Llama 3 8B、Qwen2.5 7B、DeepSeek 等不同模型在同一套 GPU 上的表现而每个模型如果都单独配一套 API Key 和地址管理成本很高。TaoToken 提供统一 Key 和统一 API 通道你可以在压测脚本里通过改 model 参数就切换后端模型不用改 base_url 和鉴权逻辑。这样基准评估的变量控制得更干净——GPU 硬件不变只变模型和并发数。这一篇我会把完整流程拆开先讲 TaoToken 的前置准备再给可复制的压测配置和采集脚本然后验证请求结果最后把常见报错逐个排查。你跟着做应该能在自己的 AMD Instinct 机器上复现出一份可对比的性能基准。2. TaoToken 统一 API 接入前置准备在开始压测之前先把 API 通道打通。TaoToken 的作用是给你一个统一的 OpenAI 兼容接口你不需要为每个模型单独申请 Key也不需要记多个 base_url。对于基准评估来说这意味着你的压测脚本只需要维护一份鉴权配置切换模型时只改 model 字段。首先去官网注册并拿到 API Key。地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台里创建 Key。控制台入口在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Keys 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。创建时建议给 Key 起个能识别的名字比如“amd-instinct-bench”方便后面在压测日志里区分。拿到 Key 之后你需要确认两件事Base URL 和可用模型列表。TaoToken 的 API 端点是 https://taotoken.net/api 注意这个地址后面不加 UTM 参数直接用于代码里的 base_url。模型列表可以在文档页 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 查看或者直接调 /v1/models 接口拉取。这里有个容易踩的坑很多人把 base_url 写成 https://taotoken.net/api/v1 或者 https://taotoken.net/v1结果请求 404。正确的写法是 base_url https://taotoken.net/apiOpenAI SDK 会自动拼接 /v1/chat/completions。如果你用的是 requests 直接发那完整地址就是 https://taotoken.net/api/v1/chat/completions。另外如果你打算在压测里同时对比多个模型建议先在控制台确认哪些模型当前可用。有些模型可能因为负载或版本调整暂时下线压测脚本里如果写死了不存在的 model id会直接返回 404 或 model not found。我一般会先跑一个最小请求验证连通性再开始正式压测。对于长期做编码和 Agent 场景的读者如果压测之后要进入持续开发阶段可以关注 Coding Plan 页面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 它更适合需要稳定调用通道的长期项目。但本篇的重点还是基准评估所以先把单次压测跑通。3. 可复制的并发压测配置与采集脚本这一节是核心操作部分。我会给出完整的 vLLM benchmark_serving.py 调用命令、TaoToken 的 OpenAI 兼容配置片段以及一个采集 GPU 指标的脚本。你直接复制改参数就能用。先确认你的 vLLM 版本和 benchmark 脚本路径。ROCm 环境下 vLLM 安装后benchmark_serving.py 通常在benchmarks/目录下。如果你是用 pip 装的可能在 site-packages 里建议直接从 vLLM 源码仓库拉一份 benchmark 目录避免路径问题。压测命令的核心参数如下python benchmarks/benchmark_serving.py \ --backend openai-chat \ --base-url https://taotoken.net/api \ --api-key $TAOTOKEN_API_KEY \ --model meta-llama/Meta-Llama-3-8B-Instruct \ --dataset-name sharegpt \ --dataset-path ./ShareGPT_V3_unfiltered_cleaned_split.json \ --num-prompts 200 \ --request-rate 0 \ --max-concurrency 64 \ --trust-remote-code这里有几个参数需要解释。--backend openai-chat表示走 OpenAI 兼容的 chat 接口TaoToken 正好兼容这个格式。--request-rate 0表示不限速让请求尽可能快地打出去这样才能压出真实并发上限。--max-concurrency 64是并发上限你可以从 1、2、4、8、16、32、64 逐档调整。--num-prompts 200是总请求数太小了统计不稳定太大了压测时间过长200 是个比较平衡的值。如果你想把并发梯度做成自动化可以写一个 shell 循环for concurrency in 1 2 4 8 16 32 64; do echo Testing concurrency: $concurrency python benchmarks/benchmark_serving.py \ --backend openai-chat \ --base-url https://taotoken.net/api \ --api-key $TAOTOKEN_API_KEY \ --model meta-llama/Meta-Llama-3-8B-Instruct \ --dataset-name sharegpt \ --dataset-path ./ShareGPT_V3_unfiltered_cleaned_split.json \ --num-prompts 200 \ --request-rate 0 \ --max-concurrency $concurrency \ --save-result \ --result-dir ./bench_results/concurrency_$concurrency done--save-result会把每次压测的 JSON 结果存下来后面做曲线对比很方便。接下来是 GPU 指标采集。AMD Instinct 上用rocm-smi可以实时看显存带宽和利用率但要做成时间序列建议用rocm-smi --json配合脚本定时抓取#!/bin/bash # gpu_monitor.sh INTERVAL1 OUTPUT./gpu_metrics.csv echo timestamp,gpu_use,mem_use,temp,power $OUTPUT while true; do TS$(date %s) METRICS$(rocm-smi --showuse --showmemuse --showtemp --showpower --json 2/dev/null) GPU_USE$(echo $METRICS | jq -r .[card0][GPU use (%)] 2/dev/null) MEM_USE$(echo $METRICS | jq -r .[card0][GPU memory use (%)] 2/dev/null) TEMP$(echo $METRICS | jq -r .[card0][Temperature (Sensor edge) (C)] 2/dev/null) POWER$(echo $METRICS | jq -r .[card0][Average Graphics Package Power (W)] 2/dev/null) echo $TS,$GPU_USE,$MEM_USE,$TEMP,$POWER $OUTPUT sleep $INTERVAL done这个脚本每秒抓一次输出 CSV压测结束后你可以用 pandas 或 Excel 画图。注意jq需要提前安装字段名可能因 ROCm 版本略有差异先用rocm-smi --json单独跑一次确认 key 名。如果你用的是 Cline MCP 或 Claude Code 这类工具做辅助开发配置里需要写全三件套Base URL、API Key、Model ID。比如在 Cline 的 MCP 配置里{ mcpServers: { taotoken: { command: npx, args: [-y, taotoken/mcp-server], env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: sk-xxxxxxxx, TAOTOKEN_MODEL: meta-llama/Meta-Llama-3-8B-Instruct } } } }Codex 的 auth.json 也是类似逻辑把 base_url 和 key 写进去model 单独指定。这些配置在压测之外但如果你要在同一台机器上做开发调试提前配好能省很多切换时间。4. 验证请求与成功结果解读压测跑完之后benchmark_serving.py 会输出一份统计摘要包含 RPS、TPS、TTFT、TPOT 等指标。你需要重点看三个数请求吞吐RPS、Token 吞吐TPS和首字延迟TTFT。下面是我在 AMD Instinct ROCm 7.x 环境下实测的一组典型结果你可以对照自己的数据看趋势。低并发阶段1 到 8 并发TTFT 稳定在 50ms 左右TPS 随并发数近似线性增长。这说明 PagedAttention 的显存管理在低负载下效率很高GPU 计算单元没有成为瓶颈。这个阶段你可以放心把并发往上加延迟不会明显恶化。当并发到 16 和 32 时曲线开始出现非线性。RPS 增速放缓TTFT 从 50ms 逐步爬到 120ms 左右。这时候显存带宽利用率大概在 70% 到 85% 之间说明数据搬运开始吃紧。连续批处理机制还在工作但每个 batch 里的序列数增多调度开销和 KV Cache 换入换出变频繁。到 64 并发时典型的性能拐点出现TPS 不再增长甚至略有下降TTFT 飙到 200ms 以上。用 rocm-smi 实时看显存带宽利用率接近饱和GPU 计算利用率反而没有满载。这说明瓶颈在显存带宽不在算力。这时候如果你继续加并发延迟会进一步恶化但吞吐不会提升属于无效加压。针对这个现象调整--max-num-seqs参数能有效平滑延迟。这个参数限制单批次最大序列数默认值可能偏高导致调度器一次塞太多请求进 batch。把它设成 32 或 16让 batch 更小但更稳定TTFT 曲线会明显平缓。生产环境建议把并发阈值设在拐点前的 80% 处比如拐点在 64那日常并发控制在 48 到 50 左右留出突发余量。验证请求是否真正走通 TaoToken 通道可以单独发一个最小请求curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: meta-llama/Meta-Llama-3-8B-Instruct, messages: [{role: user, content: Say hello in one word.}], max_tokens: 10 } | jq .如果返回里有choices[0].message.content说明通道正常。如果返回 401检查 Key 是否复制完整如果返回 model not found检查 model id 是否在文档列表里。压测结果 JSON 里还会记录每个请求的延迟分布你可以用 Python 画 P50、P95、P99 曲线。P99 延迟比平均延迟更能反映用户体验尤其在高并发下长尾请求往往是因为 KV Cache 争抢或调度排队。我一般会把 P99 和显存带宽利用率放在同一张图里看相关性非常明显。5. 本篇常见报错排查压测过程中最容易遇到的几个报错我按出现频率排一下并给出排查路径。第一个是 401 Unauthorized。这个最常见原因通常是 API Key 没传对。检查三点Key 是否复制了完整字符串有时候复制会漏掉开头或结尾字符请求头里是否是Authorization: Bearer sk-xxx格式注意 Bearer 后面有空格如果你用的是环境变量确认$TAOTOKEN_API_KEY在当前 shell 里确实有值可以用echo $TAOTOKEN_API_KEY验证。另外如果你在 Docker 容器里跑压测环境变量可能没传进去需要在docker run时加-e TAOTOKEN_API_KEYxxx。第二个是 local proxy failed 或 connection refused。这个通常不是 TaoToken 的问题而是你本机网络配置或代理设置导致的。检查你的http_proxy和https_proxy环境变量如果指向了一个不可用的本地代理请求会直接失败。用env | grep -i proxy看一下如果有不需要的代理设置临时 unset 掉再试。另外确认你的 DNS 能解析 taotoken.net可以用nslookup taotoken.net验证。第三个是 reading choices 相关报错比如KeyError: choices或reading choices。这通常是因为返回体不是标准的 OpenAI 格式可能是请求打到了错误的 endpoint。检查你的 base_url 是不是写成了https://taotoken.net/api/v1如果是改成https://taotoken.net/api。还有一种可能是 model id 写错了服务端返回了错误信息而不是正常的 choices 数组。先用 curl 单独发一个请求看原始返回是什么。第四个是 OAuth 或鉴权相关报错。如果你在用 Claude Code 或类似工具配置里可能混用了 OAuth token 和 API Key。TaoToken 走的是 API Key 鉴权不需要 OAuth 流程。检查你的配置文件里是否有多余的 OAuth 字段删掉后只保留 base_url、api_key 和 model。Claude Code 的配置可以参考文档页 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有各工具的接入示例。第五个是压测脚本报max concurrency reached或请求超时。这可能是服务端限流或你的并发设得太高。先把--max-concurrency降到 1确认单请求能通再逐步往上加。如果单请求正常但高并发超时检查你的客户端是否有连接池限制Python 的 requests 默认连接池可能不够用可以在 benchmark 脚本里调大--max-concurrency对应的连接数。第六个是 rocm-smi 采集脚本报 jq 解析错误。这通常是 ROCm 版本不同导致 JSON 字段名变化。先单独跑rocm-smi --showuse --json看实际输出的 key 是什么然后改脚本里的 jq 表达式。如果 jq 没装用apt install jq或dnf install jq装上。排查顺序建议从简到繁先用 curl 验证通道再跑单请求压测最后上高并发。每一步都确认通过再进下一步这样出问题时能快速定位是哪一层的问题。6. 从压测到生产持续调用与模型对比压测跑完、拐点找到之后下一步就是把这套评估方法用到日常模型对比和容量规划里。你可以在同一台 AMD Instinct GPU 上用同一套压测脚本只改 model 参数就能对比 Llama 3 8B、Qwen2.5 7B、DeepSeek 等模型在同一硬件上的 TPS 和 TTFT 差异。这种对比比看厂商宣传页靠谱得多因为变量控制在你手里。如果你需要长期做这类基准评估或者要把压测能力集成到 CI 流程里可以考虑用 Coding Plan 提供的稳定调用通道。它的优势是并发配额和稳定性更适合自动化任务不会因为单次压测流量大而被限流。具体可以看 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。对于需要交互式验证模型输出的场景比如你想手动问几个问题看看模型在 AMD GPU 上的实际生成质量可以用模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。它适合快速抽检不用写代码。最后说一个实用技巧压测结果不要只看单次数据建议同一并发档位跑三次取中位数排除冷启动和缓存波动。AMD Instinct 的显存带宽优势在长序列场景下更明显如果你的业务输入长度普遍超过 2K token可以把 ShareGPT 数据集换成更贴近你业务分布的样本这样拐点位置会更准。压测的最终目的不是跑出一个漂亮数字而是知道你的服务在什么并发下开始劣化以及劣化时该调哪个参数。