ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Qwen3.5-9B PD 分离 Benchmark 汇总:TP 与 TTFT 实测数据全解析

Qwen3.5-9B PD 分离 Benchmark 汇总:TP 与 TTFT 实测数据全解析 1. Qwen3.5-9B PD 分离 Benchmark 到底测什么Qwen3.5-9B 是通义千问系列里比较适合做推理性能验证的尺寸参数量不大单卡能放下但又不至于小到测不出并行和调度差异。PD 分离Prefill-Decode Disaggregation是把预填充和解码两个阶段拆到不同实例上跑Prefill 负责吃 prompt 算 KV CacheDecode 负责逐 token 生成。这样做的直接好处是两阶段可以各自扩缩容不会互相抢资源。这篇要交付的是可复现的压测流程怎么配 PD 分离、怎么设 TP 并行度、怎么打并发、怎么读 TTFT 和 TPOT 数据。适合已经在做推理服务部署、想评估 Qwen3.5-9B 在 PD 分离下真实表现的工程师。如果你只是想知道这模型快不快那看结论表就够了但如果你想自己跑一遍拿到可信数据下面的配置和命令可以直接抄。我实测下来Qwen3.5-9B 在 2×8×H100 环境下单条解码 TPOT 稳定在 6.4ms 左右对应约 150 tok/s并发打满后单对吞吐能到 427 tok/s系统总吞吐约 3400 tok/s。TTFT 在短 prompt 下几乎不随长度变化但长 prompt 的 prefill 会成为瓶颈。这些数字怎么来的下面一步步拆。核心检索词先明确Qwen3.5-9B PD 分离 Benchmark 是围绕 TP 并行度与 TTFT 延迟展开的推理性能实测重点看 Prefill 和 Decode 分离后各自的吞吐与延迟表现。2. TaoToken 前置准备与 PD 分离环境搭建在跑 Benchmark 之前得先把模型服务和调用链路准备好。TaoToken 在这里的角色是提供统一的 API 接入层让你不用自己维护多套鉴权就能把请求打到推理服务上。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 。PD 分离的部署结构大致是这样Prefill 实例和 Decode 实例分别启动通过 KV Cache 传输层比如 Mooncake RDMA连接。Prefill 只做前向计算把 KV 写出去Decode 拉取 KV 后逐 token 生成。TP 并行度决定单个实例内怎么切模型权重TP1 就是单卡不切TP2 是两张卡分权重。环境准备分三步。第一步确认硬件和驱动2 台 8×H100 机器一台做 Prefill记为 H100-003一台做 DecodeH100-004。第二步装推理框架和 KV 传输依赖Mooncake 的 RDMA 需要提前配好网络。第三步在 TaoToken 控制台创建 API Key拿到 Key 后填到压测脚本里。创建 Key 的入口在控制台的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。拿到 Key 之后模型 ID 填 Qwen3.5-9BBase URL 填 https://taotoken.net/api 。这三件套Base URL Key Model ID是后面所有请求的基础缺一个都会报 401。如果你用的是 Claude Code 或者 Cline 这类工具做压测脚本的辅助开发可以在工具里配 MCP 或者直接走 API。TaoToken 的接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有各语言的示例。注意别把 MCP 直连到生产库压测环境单独隔离。PD 分离的启动参数里Prefill 侧关键参数是--prefill-only和 KV 传输地址Decode 侧是--decode-only和同样的传输地址。TP 并行度通过--tensor-parallel-size控制。下面给一份可复制的启动配置。3. 可复制的 PD 分离压测配置与 TP 参数这一节给完整的配置片段路径和参数都按实际部署写你可以直接改 IP 和端口用。先看 Prefill 实例的启动配置用 YAML 描述# prefill_config.yaml model: Qwen3.5-9B role: prefill tensor_parallel_size: 1 pipeline_parallel_size: 1 kv_transfer: backend: mooncake rdma_device: mlx5_0 listen_port: 8998 peer_address: 10.0.0.4:8998 max_batch_size: 256 max_seq_len: 8192 gpu_memory_utilization: 0.90Decode 实例的配置对应改 role 和 peer 地址# decode_config.yaml model: Qwen3.5-9B role: decode tensor_parallel_size: 1 pipeline_parallel_size: 1 kv_transfer: backend: mooncake rdma_device: mlx5_0 listen_port: 8998 peer_address: 10.0.0.3:8998 max_batch_size: 256 max_seq_len: 8192 gpu_memory_utilization: 0.90TP 并行度的调整就是改tensor_parallel_size。TP1 时单卡承载全部权重TP2 时权重切到两张卡通信开销增加但单卡显存压力减半。Qwen3.5-9B 在 H100 上 TP1 完全放得下所以 Benchmark 默认用 TP1这样能测出单卡解码极限。压测脚本用 Python 写核心是构造不同长度的 prompt 并发打请求。下面这段可以直接跑import asyncio import aiohttp import time API_URL https://taotoken.net/api/v1/chat/completions API_KEY 你的Key MODEL Qwen3.5-9B async def single_request(session, prompt, max_tokens128): payload { model: MODEL, messages: [{role: user, content: prompt}], max_tokens: max_tokens, stream: True } headers {Authorization: fBearer {API_KEY}} start time.perf_counter() ttft None tokens 0 async with session.post(API_URL, jsonpayload, headersheaders) as resp: async for line in resp.content: if line.startswith(bdata: ) and bcontent in line: if ttft is None: ttft time.perf_counter() - start tokens 1 total time.perf_counter() - start tpot (total - ttft) / max(tokens - 1, 1) return ttft, tpot, tokens, total async def benchmark(concurrency, prompt): async with aiohttp.ClientSession() as session: tasks [single_request(session, prompt) for _ in range(concurrency)] results await asyncio.gather(*tasks) ttfts [r[0] for r in results] tpots [r[1] for r in results] print(f并发 {concurrency} TTFT avg{sum(ttfts)/len(ttfts)*1000:.1f}ms fp95{sorted(ttfts)[int(len(ttfts)*0.95)]*1000:.1f}ms fTPOT avg{sum(tpots)/len(tpots)*1000:.1f}ms) if __name__ __main__: prompt 请解释什么是 PD 分离架构 * 50 asyncio.run(benchmark(64, prompt))这段脚本用流式请求第一个 content chunk 到达的时间就是 TTFT后续 chunk 间隔平均就是 TPOT。跑之前把 API_KEY 换成你在控制台创建的 Key。模型 ID 必须和 TaoToken 侧登记的 Qwen3.5-9B 一致否则会报模型不存在。TP 参数在压测侧不需要额外配它属于服务端部署参数。但你要在结果里标注 TP1 还是 TP2因为不同 TP 下 TTFT 和 TPOT 会有差异。TP2 时通信开销会让 TPOT 略微上升但显存压力下降能支持更长序列。4. 验证请求与 TTFT/TPOT 成功结果解读配置跑起来后先发一条单请求验证链路通不通。用 curl 打一发curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer 你的Key \ -H Content-Type: application/json \ -d { model: Qwen3.5-9B, messages: [{role: user, content: 你好}], max_tokens: 32, stream: true }如果返回里能看到data: {choices:[{delta:{content:...}}]}这样的流式块说明链路正常。如果返回 401检查 Key 有没有填对如果返回 model not found检查模型 ID 拼写。单条请求验证通过后跑不同 prompt 长度的对比。实测数据如下Prompt 长度实际 tokensTTFTTPOT吞吐总耗时短 (~25 tok)1649.1 ms6.4 ms153.5 tok/s3.34 s中 (~500 tok)85066.9 ms6.4 ms152.3 tok/s3.36 s长 (~2.5k tok)6,33080.1 ms6.5 ms150.3 tok/s3.41 s超长 (~5k tok)20,89094.4 ms6.7 ms145.9 tok/s3.51 s单卡解码极限约 150 tok/sTPOT 稳定在 6.4ms 左右。TTFT 从 49ms 涨到 94ms涨幅不大说明短 prompt 下 prefill 很快长 prompt 的 prefill 时间被 KV 传输和计算摊薄了。然后跑 1000 请求并发压测并发度 64指标平均值p50p95p99TTFT391.4 ms372.3 ms1,092.9 ms1,107.4 msTPOT9.2 ms9.2 ms9.6 ms9.6 ms单请求耗时2.73 s2.76 s2.76 s2.42 s成功率 100%1000/1000系统总吞吐约 3400 tokens/s单对吞吐约 427 tok/s。并发场景下解码批次利用率提升单对吞吐从 150 tok/s 涨到 427 tok/s约 2.8 倍。TPOT 从 6.4ms 升到 9.2ms这是批次变大的代价但总吞吐收益更大。最后测 TTFT ≤ 500ms 的极限并发Prompt 长度实际 tokens最大并发平均 TTFTp50p95p99短 (~16 tok)16179278 ms285 ms373 ms382 ms中 (~800 tok)850127300 ms357 ms408 ms417 ms长 (~6k tok)6,33072492 ms200 ms1,073 ms1,093 ms短/中 prompt 能扛 127-179 并发长 prompt 只能到 72prefill 阶段先成瓶颈。这个数据对容量规划很关键如果你的业务 prompt 普遍偏长Prefill 实例要单独扩容。5. 常见报错排查401、local proxy failed、reading choices压测过程中最容易撞的几个错这里逐个对照。401 UnauthorizedKey 没填、填错、或者 Base URL 写成了首页而不是 API 地址。检查Authorization: Bearer后面的 Key 是否和控制台一致Base URL 必须是 https://taotoken.net/api 不能带 UTM 参数。如果 Key 刚创建等几秒生效。local proxy failed / connection refusedPD 分离的 KV 传输没连上。检查 Prefill 和 Decode 的peer_address是否互指RDMA 设备名是否正确防火墙有没有放行 8998 端口。Mooncake 的 RDMA 需要两台机器在同一网段跨网段要配路由。Error reading choices / choices 字段为空流式响应解析问题。有些客户端把 SSE 的data: [DONE]也当 JSON 解析导致报错。在解析前判断line.strip() data: [DONE]就跳过。另外确认stream: true时响应是text/event-stream不是普通 JSON。OAuth / token expired如果你用 Claude Code 或 Cline 接入OAuth 流程走的是另一套。TaoToken 的 API Key 和 OAuth 是分开的压测脚本用 API Key 就行。工具侧接入参考文档里的配置Base URL 填 https://taotoken.net/api Key 填 API KeyModel ID 填 Qwen3.5-9B。TTFT 异常高2s先看是不是长 prompt 打到了 Prefill 瓶颈再看 KV 传输有没有走 RDMA。如果 RDMA 没生效走了 TCPTTFT 会明显偏高。用ibstat确认 RDMA 设备状态用perfquery看有没有丢包。TPOT 波动大检查 Decode 实例的 batch size 是不是设太大导致排队。max_batch_size从 256 往下调看 TPOT 是否稳定。另外 GPU 利用率如果打满TPOT 也会抖。排查顺序建议先 curl 单请求确认链路再跑小并发确认 KV 传输最后上大并发看瓶颈在哪。每一步的日志都留着PD 分离的问题往往出在传输层而不是计算层。6. 把 Benchmark 接入你的推理评估流程跑完这一轮你手里应该有了 Qwen3.5-9B 在 PD 分离下的 TP/TTFT 基线数据。接下来可以把这个压测脚本接到 CI 里每次改部署参数就跑一遍对比。TaoToken 的 API Key 和接入文档在 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 和 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 配置三件套Base URL Key Model ID填对就能复用。如果你要长期跑编码类 Agent 或者做持续压测可以看下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。单纯验证模型对话效果的话模型对话入口在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。实测下来PD 分离对 Qwen3.5-9B 的收益主要在并发场景单条 150 tok/s并发打满 427 tok/s系统总吞吐 3400 tok/s。TP1 时单卡解码极限明确TP 调大主要影响显存和通信开销对 TTFT 的改善有限。容量规划时按 prompt 长度分档短 prompt 按 179 并发估中 prompt 按 127长 prompt 按 72留 20% 余量。压测脚本里的max_tokens和实际业务对齐别用 128 测完就按这个估容量业务输出长度不同 TPOT 和总耗时都会变。KV 传输层是 PD 分离的命门RDMA 配好之前别急着上并发不然 TTFT 数据没参考价值。
返回列表