☰
基于Atlas 900 A3 SuperPoD推理部署Deepseek-R1性能优化实践:TaoToken统一API通道调优
2026/10/8 12:33:29 网站建设 项目流程

1. 从 517 到 608 QPM:Atlas 900 A3 SuperPoD 上 Deepseek-R1 推理部署到底卡在哪

如果你正在 Atlas 900 A3 SuperPoD 上部署 Deepseek-R1,并且被 TTFT 和 TPOT 两个指标来回拉扯,这篇实践应该能帮你少走一些弯路。Deepseek-R1 是 671B 参数的 MoE 大模型,单次推理要激活几十个专家,Prefill 阶段计算密集、Decode 阶段访存密集,两个阶段的资源诉求完全不同。Atlas 900 A3 SuperPoD 提供的是超节点级互联,节点内和节点间的通信带宽远高于普通以太组网,但这也意味着如果调度层没做好,通信等待会直接吃掉算力红利。

我这次的目标很明确:在 11 节点(7P8-1D32)集群上,把 3000 条数据集(最大输入 16k、平均输入 3.5k,最大输出 32k、平均输出 1.2k)的推理吞吐推到 600 QPM 以上,同时守住 TTFT < 2s、TPOT < 50ms 的 SLA。最终实测 608 QPM,TTFT 1.93s,TPOT 47ms。整个过程的核心思路是:Omni-Infer 套件负责调度和稀疏加速,CANN 底层负责算子级优化,而 TaoToken 统一 API 通道负责把外部请求稳定地送进集群,三者缺一不可。

适合谁看:已经在昇腾平台上跑 vLLM 或类似框架、想进一步压榨 MoE 推理性能的工程师;正在做多节点 PD 分离部署、被 Prefill/Decode 配比困扰的运维同学;以及想了解 Omni-Infer + CANN 协同优化到底能带来多少收益的技术决策者。

先说结论:单纯调大 BatchSize 或加节点,QPM 不会线性增长。真正的瓶颈在三个地方——MoE 专家负载不均导致部分卡空转、Prefill 和 Decode 的资源竞争、以及首次编译和调度开销。下面按可复制的步骤展开。

2. TaoToken 统一 API 通道前置:Key、Base URL 与模型 ID 三件套

在集群内部调优之前,先把外部请求通道理顺。TaoToken 在这里的角色是统一 API 网关:你不需要为每个推理实例单独维护一套鉴权和路由逻辑,而是通过一个 Key 和统一的 Base URL 把请求分发到后端集群。对于 Atlas 900 A3 SuperPoD 这种多节点 PD 分离的部署形态,这一点尤其重要——Prefill 节点和 Decode 节点的地址会变,但对外暴露的 API 入口不变。

你需要准备三样东西:

Base URL:https://taotoken.net/api(注意 API 调用不加 UTM 参数,保持干净)

API Key:在控制台创建,格式通常是sk-开头的一串字符。建议为压测单独建一个 Key,方便按 Key 统计 QPS 和用量。

Model ID:填你部署的模型标识,比如deepseek-r1或你自定义的别名。这个 ID 要和后端 Omni-Infer 服务注册的模型名一致,否则会返回 model not found。

如果你用的是 Claude Code 或 Cline 这类编码工具做辅助调试,配置方式略有不同。以 Claude Code 为例,需要在 settings 里指定 Anthropic 兼容端点;Cline 的 MCP 配置则走 JSON 格式。不管哪种方式,核心三件套不变:Base URL 指向https://taotoken.net/api,Key 用你创建的,Model ID 填对。

注意:不要把生产环境的 Key 硬编码在代码里。压测脚本里用环境变量读取,比如export TAOTOKEN_API_KEY=sk-xxx,然后在 Python 里os.environ.get("TAOTOKEN_API_KEY")。

创建 Key 的入口在控制台的 API Keys 页面。如果你还没注册,可以先从官网进去了解整体能力,再决定用哪种接入方式。对于长期做编码和 Agent 调用的场景,Coding Plan 会更划算;如果只是验证模型输出质量,直接用模型对话页面就行。

通道打通之后,你就可以在集群内部专注做推理性能优化了。外部请求通过 TaoToken 进来,内部由 Omni-Infer 调度到各个 PD 节点,CANN 在底层做算子加速。下面进入具体配置。

3. 可复制配置:Omni-Infer 的 PD 配比、BatchSize 与 CANN 参数

这一节直接给可复制的配置片段。我按“先定 PD 配比,再调 BatchSize,最后开 CANN 优化”的顺序来写,你可以照着改。

3.1 PD 配比与并发参数

从 4P1D 到 7P1D 的演进过程,核心是找到 QPM 和 TTFT 的平衡点。实测数据如下:

配比BatchSize/DieQPMTTFT
4P8-1D321536244较高
5P8-1D322048517偏高
6P8-1D323072613.25s
7P8-1D3231686081.93s

6P1D 时 QPM 虽然到了 613,但 TTFT 高达 5s,不满足 SLA。扩到 7P1D 并把并发提到 3168 后,TTFT 降到 1.93s,QPM 微降到 608,但整体达标。Decode 侧则通过 CANN 优化把 TPOT 从 50ms 压到 47ms,弥补了扩比带来的 QPM 平摊。

对应的 Omni-Infer 启动配置片段(JSON 格式,路径按你的实际部署调整):

{ "model": "deepseek-r1", "prefill_nodes": 7, "decode_nodes": 1, "tp_size": 8, "batch_size_per_die": 3168, "max_input_len": 16384, "max_output_len": 32768, "omni_placement": { "enable": true, "redundant_experts": 2, "dynamic_adjust_interval": 100 }, "omni_attn": { "enable": true, "compress_ratio": 0.5, "search_mode": "evolutionary" }, "omni_proxy": { "enable": true, "scheduling_policy": "OAS", "apc_aware": true } }

如果你用 TOML 管理配置,等价写法:

[model] name = "deepseek-r1" prefill_nodes = 7 decode_nodes = 1 tp_size = 8 batch_size_per_die = 3168 [omni_placement] enable = true redundant_experts = 2 dynamic_adjust_interval = 100 [omni_attn] enable = true compress_ratio = 0.5 search_mode = "evolutionary" [omni_proxy] enable = true scheduling_policy = "OAS" apc_aware = true

3.2 CANN 底层优化开关

Micro-Batch 双流水线、SuperKernel、TorchAir 图缓存这三个优化,在 CANN 侧通过环境变量和编译选项控制:

export ASCEND_OMNI_MICRO_BATCH=2 export ASCEND_OMNI_STREAM_SPLIT=1 export ASCEND_SUPERKERNEL_ENABLE=1 export ASCEND_SUPERKERNEL_FUSION_LAYERS=58 export TORCHAIR_CACHE_COMPILE=1 export TORCHAIR_CACHE_DIR=/data/torchair_cache

Micro-Batch 分核策略按序列长度区分:长序列时 attn 流按 16:32 分 AIC/AIV 核,MoE 按 8:16 分;短序列时 attn 核数减半。这个逻辑在 Omni-Infer 内部自动判断,你只需要把ASCEND_OMNI_MICRO_BATCH设为 2 即可启用双流水线。

SuperKernel 目前支持把 DeepSeek-R1 的 61 层网络中的 58 层融合为 1 个超级内核,整网收益平均 10~20%。TorchAir 的 cache_compile 则把 Decode 阶段的首次编译结果落盘,TPOT 提升约 2ms。

注意:TorchAir 缓存目录要确保有写权限,且不同模型版本不要混用同一个缓存目录,否则可能出现图不匹配的报错。

4. 验证请求与成功结果:压测脚本与指标观测

配置改完后,别急着上全量。先用小批量请求验证通道和推理链路是否正常,再逐步加压。

4.1 单请求连通性验证

用 curl 直接打 TaoToken 的 API 端点:

curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-r1", "messages": [{"role": "user", "content": "用一句话解释MoE专家负载均衡"}], "max_tokens": 128, "stream": false }'

如果返回正常,你会看到choices数组里有内容,usage字段显示 token 消耗。这一步验证的是 TaoToken 通道 + 后端 Omni-Infer 服务是否都活着。

4.2 压测脚本与 QPM 计算

用 Python 写一个并发压测脚本,模拟 3000 条数据集的请求模式:

import asyncio import aiohttp import time import os API_URL = "https://taotoken.net/api/v1/chat/completions" API_KEY = os.environ.get("TAOTOKEN_API_KEY") async def send_request(session, prompt, max_tokens=1200): payload = { "model": "deepseek-r1", "messages": [{"role": "user", "content": prompt}], "max_tokens": max_tokens, "stream": False } headers = {"Authorization": f"Bearer {API_KEY}"} start = time.time() async with session.post(API_URL, json=payload, headers=headers) as resp: data = await resp.json() elapsed = time.time() - start return elapsed, data.get("usage", {}) async def main(): prompts = ["请解释注意力机制" for _ in range(3000)] async with aiohttp.ClientSession() as session: tasks = [send_request(session, p) for p in prompts] results = await asyncio.gather(*tasks) total_time = max(r[0] for r in results) qpm = len(results) / total_time * 60 print(f"QPM: {qpm:.1f}, 总耗时: {total_time:.1f}s") asyncio.run(main())

跑完后看 QPM 是否接近 608。如果明显偏低,先检查并发数是否设够,再看 Prefill 节点是否有排队。

4.3 关键指标观测

TTFT 和 TPOT 需要从服务端日志或监控面板读取。Omni-Infer 的 OmniProxy 会收集请求级和实例级指标,包括提示长度、前缀匹配分数、队列长度、吞吐量等。你可以在 Grafana 里建面板,重点看三个曲线:Prefill 队列深度、Decode 队列深度、TPOT 滑动平均。

实测达标时的数据:TTFT 1.93s,TPOT 47ms,QPM 608。如果 TTFT 偏高,优先加 Prefill 节点或提高 Prefill 并发;如果 TPOT 偏高,检查 Decode 侧的 SuperKernel 和 TorchAir 缓存是否生效。

5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth

这一节按真实报错来写,你遇到哪个直接对号入座。

401 Unauthorized:最常见的原因是 Key 没传对。检查Authorization头是不是Bearer sk-xxx格式,Key 有没有多余空格。如果你用的是 Claude Code 或 Cline,确认 settings 里的 Base URL 是https://taotoken.net/api,而不是带 UTM 的官网地址。另外,Key 如果被禁用或过期,也会返回 401,去控制台 API Keys 页面确认状态。

local proxy failed:这个报错通常出现在本地调试工具通过代理转发请求时。先确认你的环境变量里没有残留的HTTP_PROXY或HTTPS_PROXY指向不可用的地址。如果是 Cline 的 MCP 配置,检查 JSON 里的baseUrl是否写成了https://taotoken.net/api,不要多写/v1或漏写。MCP 配置示例:

{ "mcpServers": { "taotoken": { "command": "npx", "args": ["-y", "@taotoken/mcp-server"], "env": { "TAOTOKEN_API_KEY": "sk-xxx", "TAOTOKEN_BASE_URL": "https://taotoken.net/api" } } } }

reading choices 报错:一般是响应体里没有choices字段,说明后端返回了错误信息但你的代码直接去读choices[0]。加一层判断:

if "choices" not in data: print("错误响应:", data) return

常见原因是 Model ID 写错,或者 max_tokens 超过了模型上限。Deepseek-R1 最大输出 32k,你设 128k 就会报错。

OAuth 相关报错:如果你用 Codex 的 auth.json 方式接入,确认文件路径和格式正确。auth.json 里需要包含api_key和base_url两个字段,base_url 指向https://taotoken.net/api。如果报 token 无效,重新生成 Key 并更新 auth.json。

QPM 上不去:先看 Prefill 队列是否堆积。如果 Prefill 队列长期大于 0,说明 Prefill 节点不够,加节点或提高 BatchSize。如果 Decode 队列堆积,检查 TPOT 是否超标,开 SuperKernel 和 TorchAir 缓存。另外,OmniPlacement 的动态调整间隔不要设太小,否则权重迁移频繁反而影响吞吐,100 个 step 左右比较合适。

TTFT 突然升高:检查是否有长序列请求集中打进来。长序列的 Prefill 计算量大,会阻塞短序列。OmniProxy 的 APC 感知调度可以缓解这个问题,确认apc_aware设为 true。如果还是高,考虑把长序列请求单独路由到专用 Prefill 节点。

6. 语义一致 CTA:从通道调优到长期编码的接入选择

整篇下来,核心链路是:TaoToken 统一 API 通道负责外部请求接入和鉴权,Omni-Infer 负责集群内的 PD 调度和稀疏加速,CANN 负责算子级优化。三者协同,才能在 Atlas 900 A3 SuperPoD 上把 Deepseek-R1 的 QPM 推到 608。

如果你正在做类似的推理部署调优,建议先把 TaoToken 的 Key 和 Base URL 配好,用单请求验证通道,再上压测脚本。遇到 401 或 local proxy failed,按第 5 节的排查步骤走。需要创建 Key 或查看接入文档,可以从 API Keys 页面和控制台入口进去。如果你更关注模型输出质量验证,直接用模型对话页面测试;如果是长期编码和 Agent 调用场景,Coding Plan 的用量模型会更适合。

配置改完后,记得把 TorchAir 缓存目录持久化,下次服务重启能直接复用编译结果,省掉首次编译的等待时间。这个细节在弹性扩容场景下尤其有用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询