跳到主要内容

14 篇博文 含有标签「latency」

查看所有标签

GPU 饥饿:某个租户的推理提示词如何导致你的共享推理端点停滞

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的仪表盘显示 GPU 状态健康。利用率维持在 80% 左右,每秒生成的 token 吞吐量看起来很正常,冷启动很少见,而且模型也是你要求的那个。然而,你的报警器响了,因为 p99 延迟翻了三倍,少数用户遇到了超时,支持工单都在描述同一件事:“应用冻结了 20 秒,然后又恢复了。” 你调取了一个追踪(trace),发现一个毫不相关的客户发送的 28,000 个 token 的推理请求,正与每一个停滞的调用处在同一个批次(batch)中。某个租户的深度思考提示词刚刚抢走了其他所有人的机会。

这就是队头阻塞(head-of-line blocking),它是推理模型进入流量组合后,破坏共享 LLM 推理的典型故障模式。这种模式并不新鲜 —— 存储系统和网络栈已经与之斗争了几十年 —— 但由于连续批次(continuous batching)和 KV 缓存固定(KV-cache pinning)的工作方式,它在 GPU 上呈现出一种特定的形态。大多数团队针对平均负载进行设计,却太晚才发现,一旦请求大小不再相似,“共享推理更便宜”就不再成立了。

你的 P99 正在受陌生人流量的影响:托管 LLM 推理中的“吵闹邻居税”

· 阅读需 13 分钟
Tian Pan
Software Engineer

你的仪表板很干净。昨天的部署也已干净地回滚。模型版本已锁定。提示词没有更改。但你的 TTFT p99 刚刚翻了一倍,客户成功渠道已经炸锅了,而你唯一能给出的诚实回答是“这是提供商的问题”。这个答案显得很苍白——就像耸耸肩一样——它通常会引出一个团队中没人能回答的后续问题:证明它。

这是托管 LLM 推理中营销页面不会讨论的部分。当你调用前沿模型 API 时,你正在与你看不见的负载共享 GPU、PCIe 结构、连续批处理和 KV 缓存预算。你的 p99 是这些负载突发的函数。大规模推理的经济性取决于租户的多路复用是否足够紧密,以使硬件利用率保持在 60-70% 以上,这意味着你的尾部延迟在结构上与同一分片上最大、最不规整、最不稳定的租户耦合。你购买的不是容量;你购买的是一个别人也排在其中的队列切片。

现在,推理速度已经快过你的数据库了

· 阅读需 12 分钟
Tian Pan
Software Engineer

打开任何 2024 年时代的 AI 功能链路追踪 (trace),模型调用就像是一头巨鲸。八百毫秒的生成时间,包裹在检索、鉴权和数据库查询组成的薄壳中,后者的时间几乎可以忽略不计。那一年的每一个架构决策——缓存、预取、流式 UX——都是为了隐藏那头“巨鲸”。

现在,查看运行在 2026 年推理栈上的相同功能的链路追踪。那头巨鲸已经变成了一只海豚。缓存后的预填充 (prefill) 在 180ms 内返回第一个 token。解码 (decode) 以每秒 120 个 token 的速度流式传输。模型不再是慢节点。你自己的基础设施才是,而且大部分基础设施还没有意识到这一点。

这种顺序重排是今年最重要的性能转变,也是各团队一直反应不足的一个。现在,AI 请求的 p99 底限是由特征存储 (feature store) 调用、鉴权中间件以及那些一直都很慢的 Postgres 查询决定的——在模型占据九成预算时,没人关心这些。

你的 LLM Span 在撒谎:APM 工具没告诉你的推理延迟真相

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的 LLM 调用耗时 2,340 毫秒。你的 APM Span 是这么记录的。这个数字是你可观测性堆栈中最昂贵的谎言,因为四种完全不同的故障模式都被渲染成了同一个不透明的紫色条块。长提示词下的 Prefill(预填充)浪涌。一个一小时没访问的租户导致的冷 KV 缓存。提供商连续批处理(continuous batching)中的“吵闹邻居”。一次无声的路由变更将你的流量导向了不同的区域。同样的 Span。同样的耗时。同样的 p99 告警。却是四个截然不同的复盘分析。

适用于微服务的分布式追踪准则 —— 每个网络跳数一个 Span、一个时长、几个标签 —— 在面对托管推理时失效了。LLM 调用并非单一实体。它是一个由多个阶段组成的流水线,每个阶段都有截然不同的扩展特性,运行在行为取决于队列中其他人的共享硬件上。将其视为一个单一且不透明的 Span,会导致你花费三天时间去调试“模型变慢了”,而实际上模型根本没变。

首字延迟 (TTFT) 是你尚未监测的延迟 SLO

· 阅读需 12 分钟
Tian Pan
Software Engineer

调出过去一周的生产环境追踪记录,查看你的延迟仪表板。你几乎肯定在总请求延迟上设置了 p50 和 p99。你可能还有令牌吞吐量(token throughput)。你甚至可能有一张每秒令牌数(tokens-per-second)图表,因为某个供应商的基准测试说服你这么做了。但你几乎肯定没有的是按模型、按路由、按租户划分的**首字时间(time to first token, TTFT)**直方图 —— 这是决定你产品感知速度的核心指标。

这绝非一个小疏忽。对于任何流式界面 —— 聊天、代码补全、智能体侧边栏、语音 —— 用户感知的速度取决于在内容出现之前,他们盯着闪烁光标的时间。一旦第一个令牌(token)出现,用户就开始进入阅读状态;随后的令牌是在与他们的阅读速度竞争,而不是与他们的耐心竞争。总延迟(Total latency)对于吞吐量规划和成本预算很重要,而 TTFT 则决定了产品是否让人感觉“有生命力”。

这两个数字之间的差距正在拉大。推理模型(Reasoning models)产生的总延迟可能与其非推理兄弟模型完全相同,但却会将 TTFT 从 400 毫秒推高到 30 秒。一个“保持延迟持平”的路由更改,可能会悄无声息地将一个反应灵敏的助手变成一个卡死的窗口。如果你没有对 TTFT 进行图表化,你就是在发布连你自己都察觉不到的 UX 退化。

语音智能体并非带麦克风的聊天机器人:半双工税

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个在所有转写层级基准测试(benchmark)中得分完美的语音智能体,在实际通话中可能仍然让人感觉有些微妙的不对劲。文字没错,推理也没错。仪表盘上的端到端延迟显示为 520ms,这正是预期的目标。然而,电话另一端的人却不断卡顿、抢话、重说,甚至提前挂断。团队发布了更好的模型,数据提升了,但体感依然没有改善。

究其原因,与模型说了什么几乎无关,而与它何时说话几乎全盘相关。语音并非仅仅是附带了音频的文本。人类的对话运行在一个严密的半双工(half-duplex)协议之上,包含插话(barge-in)、反馈信号(backchannel)和重叠语音,其时间预算是以毫秒计算的。大多数语音智能体的问题,在解决了第一周的幻觉修复后,本质上都是轮次协商(turn-negotiation)问题。而轮次协商是架构层面的问题——你无法通过提示词工程(prompting)来解决它。

串行工具调用瀑布:Agent循环中隐藏的延迟税

· 阅读需 10 分钟
Tian Pan
Software Engineer

如果你曾剖析过一个莫名其妙跑得很慢的AI Agent,大概率会发现一个瀑布。Agent调用工具A,等待,再调用工具B,等待,再调用工具C——即便B和C根本不依赖A的结果。你为1倍的工作量付出了3倍的延迟。

这个模式并非边缘情况,而是几乎所有Agent框架的默认行为。模型在单次响应中返回多个工具调用,执行循环则逐一按顺序运行它们。修复并不复杂,但前提是要有一种可靠的方法来识别哪些调用真正相互独立。

Agent 链中的截止时间传播:第三跳时你的 p95 SLO 发生了什么

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数构建多步 agent 管道的工程师会在第一次生产故障后约两周发现同一个问题:他们在 API 网关设置了 5 秒超时,但 agent 管道有四跳,而整个系统的行为就好像根本没有超时一样。第三跳的 agent 不知道上游调用方三秒前就已放弃等待,它继续运行、继续调用工具、继续生成 token——而用户早已离开。

这不是配置错误,而是结构性问题。延迟约束默认不会跨 agent 边界传播,主流编排框架也没有任何一个让截止时间传播变得容易。结果是一类看起来像延迟问题、实则是上下文传播问题的故障。

智能体加载状态难题:为 45 秒的 UX 深渊进行设计

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的产品在第 10 秒到第 45 秒之间存在一个“空洞”,在这个时间段内,你设计的任何东西都不再起作用。用户在 10 秒左右就会放弃无响应的 UI —— Jakob Nielsen 在 90 年代就确定了这个阈值,现代的眼动追踪研究显示的偏差也不过一两秒。现代智能体(Agent)的工作通常需要 30 到 120 秒。多步规划、检索、几次工具调用,可能在最终输出前还要经过一轮反思 —— 延迟预算不再只是预算,而是一个巨大的深渊。

大多数团队在第一次发布智能体功能并查看会话录像时都会发现这一点。用户疯狂点击提交按钮。他们将查询粘贴到第二个标签页中。他们关闭窗口并从头开始重试,坚信系统已经崩溃。功能本身没问题,但等待过程出了问题。“加载动画出现”与“答案送达”之间的空白地带是 AI 产品设计中最被忽视的环节,而它正是决定用户认为你的智能体是聪明还是死机的关键。

热路径与冷路径 AI:决定你 p99 延迟的架构决策

· 阅读需 12 分钟
Tian Pan
Software Engineer

你发布的每一个 AI 功能,在成为产品决策之前,都首先是一个架构选择:这个模型调用是发生在用户的请求链路中,还是在用户无需等待的地方运行?这个选择通常由编写第一个原型的人做出,之后便不再被审视,并默默地决定了该功能在余下生命周期中的 p99 延迟。当事后分析(Post-mortem)询问为什么生产环境仪表盘在每周一上午 10 点变得无法使用时,答案几乎总是:某些本应属于冷路径(Cold-path)的东西被焊死在了热路径(Hot-path)中——而在 p50 时表现良好的模型,在流量扇出(Fan out)时,其 p99 的表现会变得极具灾难性。

热路径与冷路径的区别比 LLM 还要早。CQRS、流式架构、Lambda 架构——它们都在“必须立即响应”和“可以最终送达”之间划定了相同的界限。AI 工作负载的不同之处在于,走错方向的代价比以前高出了一个数量级。一个耗时 50 ms 的同步数据库查询变成 200 ms 是一次回归(Regression)。而一个在 p50 时耗时 1.2 秒的同步 LLM 调用在 p99 时变成 11 秒,则是你无意中做出的一项商业决策。

没人调校的 max_tokens 旋钮:将输出截断作为成本杠杆

· 阅读需 12 分钟
Tian Pan
Software Engineer

检查你代码库中每一次 LLM 调用里的 max_tokens 参数。如果你和大多数团队一样,这个参数要么没设置,要么设成了模型的最大值,或者是半年前随便选的一个像 4096 这样的整数,之后就再也没动过。它是 API 请求中一个显眼的预算旋钮,却在默默地为你从未使用过的冗余买单。

在中等商业模型上,输出 token 的成本大约是输入 token 的四倍,而在昂贵模型上甚至高达八倍。生成步骤的经济效益完全是失衡的:你在 max_tokens 中留下的每一分未使用的余量,都是你可能需要支付的成本;而且由于解码是顺序进行的,你生成的每一个 token 都会线性地增加你的 P50 延迟。然而,大多数生产系统都将此参数视为安全阀——设置得高高的,然后忘掉它,继续开发。

设计不拖垮延迟的 AI 安全层

· 阅读需 10 分钟
Tian Pan
Software Engineer

大多数团队引入护栏的方式,和引入日志一样随意:直接挂上去,以为代价很小,然后继续往下走。但代价并不小。一次内容审核检查要花 10–50ms,再加上 PII 检测,又是 20–80ms;再叠上输出 schema 校验和毒性分类器,在第一个 token 到达用户之前,串行开销就已累积到 200–400ms。加上 500ms 的模型响应,你那个"快速"的 AI 功能现在给人的感觉就是迟钝。

把锅甩给 LLM 是错的。护栏才是瓶颈。解决方案不是去掉安全措施,而是停止把安全检查当成一堆无差别的任务,改用架构思维来对待它。