摘要:大模型推理的延迟不是一个“服务器快不快”的问题,而是两阶段计算特性(Prefill / Decode)与承载层控制权分配的结果。本文将剥离营销术语,从 Transformer 推理的计算本质出发,拆解 TTFT 与 TPOT 的成因,映射到 AWS 上的三种承载形态(Bedrock 无服务器托管 / SageMaker 托管端点 / HyperPod 自建),并指出流式响应在 API Gateway、Lambda 与 CDN 链路上是如何被中间层悄悄“吃掉”的。
1. 延迟的两个来源:Prefill 与 Decode
在讨论“选哪个服务”之前,必须先明确一件事:一次大模型请求的时间,由两个物理性质完全不同的阶段构成。承载层的选型,本质上是在选择你对这两个阶段有多少控制权。
1.1 Prefill(预填充):计算密集阶段
请求到达后,模型要把整个输入(system prompt + 历史对话 + 检索到的上下文 + 用户问题)一次性前向计算一遍,生成每个位置的 K/V 并写入 KV Cache。
- 特征:算力受限(compute-bound),大量矩阵乘法,GPU 的 Tensor Core 利用率可以打满。
- 代价:计算量随输入长度增长,其中自注意力部分近似呈平方级增长。因此长 prompt 直接推高 TTFT(Time To First Token,首 token 延迟)。
- 结论:TTFT 的主要矛盾是 prompt 长度与算力,而不是网络。
1.2 Decode(解码):显存带宽密集阶段
首 token 之后,模型逐个生成 token。每生成一个 token,都要把此前所有位置的 KV Cache 从显存读出来做注意力计算。
- 特征:显存带宽受限(memory-bandwidth-bound),而非算力受限。GPU 大量时间在“等数据”,Tensor Core 利用率反而很低。
- 代价:每生成一个 token 的成本,与 KV Cache 的体量成正比。
- 结论:TPOT(Time Per Output Token)/ ITL(Inter-Token Latency)的主要矛盾是显存带宽与上下文长度,输出越长、上下文越长,每 token 越慢。
1.3 KV Cache 的体量公式
单个请求的 KV Cache 占用可近似表示为:
KV_Cache ≈ 2 × n_layers × n_kv_heads × d_head × bytes_per_param × seq_len- 乘 2:K 和 V 各一份;
n_kv_heads:采用 GQA / MQA 的模型该值远小于注意力头数,这正是现代模型压缩 KV Cache 的主要手段;bytes_per_param:量化(FP8 / INT8)会直接线性降低占用;- 再乘以并发 batch size,就是这张卡的显存账单。
架构含义:并发不是免费的。想提升吞吐就抬高 batch,而 batch 抬高会同时抬高显存占用与带宽竞争——吞吐与单请求延迟是一对真实存在的矛盾,continuous batching 能缓解,但不能消除。
2. 承载层的三种形态:你交出了多少控制权
AWS 上的承载层可以按“控制权”排成一条光谱。这条光谱的每一格,都对应着不同的延迟可优化空间。
| 维度 | Bedrock(无服务器) | SageMaker 托管端点 | HyperPod / EKS 自建 |
|---|---|---|---|
| 基础设施 | 完全不可见,无 GPU 管理 | 实例可见,规格可选 | 集群自建,全栈可控 |
| 可控的延迟杠杆 | prompt 结构、参数、缓存前缀 | batching 策略、量化、推理引擎、实例类型 | 全部,含算子与调度 |
| 冷启动 | 无(共享池) | 实时端点无;Serverless 有 | 取决于自身调度 |
| 计费单位 | token | 实例秒 | 实例/集群秒 |
| 适用 | 通用、快速上线、波动流量 | 稳定高负载、需定制权重与引擎 | 极致性能与成本优化 |
2.1 Bedrock:把控制权换成速度
Bedrock 通过统一 API(Converse / ConverseStream,以及 InvokeModel / InvokeModelWithResponseStream)屏蔽了模型差异,也屏蔽了底层硬件。
你能调的杠杆只有三个:
- Prompt 结构——既然 TTFT 由 prompt 长度决定,缩短前缀就是最直接的优化。
- 提示缓存(Prompt Caching)——把 system prompt、工具定义、长文档等重复前缀缓存起来,命中部分跳过 prefill 计算。AWS 官方口径为:对命中的缓存前缀,最高可降低约 85% 的延迟与 90% 的成本(均为官方上限值,实际收益取决于命中率)。这是 Bedrock 上唯一能显著改善长 prompt TTFT 的手段。
- 吞吐保障——对稳定高负载场景,可使用预置吞吐(Provisioned Throughput)锁定容量;跨区域推理(inference profile)能提升可用性,但会引入跨区网络跳数,在极致延迟场景下必须计入预算。
架构警示:Bedrock 是多租户共享服务。你无法独占硬件,因此 P99 尾延迟不在你的控制范围内。如果业务的 SLA 是“P99 < X ms 且抖动可控”,那么共享池本身就是风险项。
2.2 Bedrock Custom Model Import:中间态
若你需要自定义权重但不愿运维 GPU,Custom Model Import 是一条折中路径:导入自己的权重,部署到 Bedrock 的托管无服务器环境,用 InvokeModel / InvokeModelWithResponseStream 调用。
边界:支持的模型架构与区域是有限集合且持续变化,调用前需以官方文档为准;部分架构对 Converse API 的支持存在例外。
2.3 SageMaker 托管端点:拿回引擎控制权
当你需要自己决定 batching、量化与推理引擎时,承载层应换到 SageMaker:
- 实时端点(Real-time Endpoint):常驻实例,无冷启动,适合稳定流量;
- 推理组件(Inference Components):多模型打包到同一端点,隔离算力、独立扩缩,并支持缩容到零,把闲置 GPU 成本压下来;
- OpenAI 兼容 API:已有 OpenAI SDK / 框架的应用可低成本迁移到自有 GPU。
- Serverless Inference:缩容到零,但存在冷启动,不适合对 TTFT 敏感的实时对话。
架构收益:在这一层,你终于可以针对第 1 节的结论做工程动作——换 INT8/FP8 量化降低 KV Cache、调整 continuous batching 的并发窗口、选择带宽更高的实例类型来直接改善 TPOT。
2.4 HyperPod / EKS:把 prefill 与 decode 拆开
在自建层可以做托管层做不到的事:Prefill-Decode 分离部署。
由于两阶段一个是算力密集、一个是带宽密集,把它们放在同一批 GPU 上跑,必然互相干扰。分离部署后各自按瓶颈选型与扩缩,AWS 在 HyperPod 侧也提供了分层 KV Cache 与智能路由等面向长上下文、多轮对话的延迟优化能力。这是“混合流量下延迟一致性”的正解,代价是你接管了整条运维链路。
说明: 从左至右,你能施加影响的延迟杠杆越来越多,同时需要自己运维的层次也越来越深。选型的第一步是确定自己站在光谱的哪一格。
3. 流式响应:别让中间层吃掉你的优化
一个高频误解:流式不改变总生成时间,只改变“可感知延迟”。用户看到第一个字的时间提前了,但最后一个字的时间一点没变。若链路中任一环节缓冲,连这个感知收益都会消失。
3.1 链路上的三个缓冲点
Client → CloudFront/CDN → API Gateway → Lambda → Bedrock- API Gateway(默认 BUFFERED):默认会等后端完整返回再转发。同时它有两类硬约束——29 秒集成超时与 10 MB 响应上限。长文本生成很容易撞上前者,表现为客户端收到 504。
- CDN / 反向代理:自有 CloudFront 分发或前置 Nginx 有自己的响应超时与缓冲策略,同样会积压 chunk。
- 客户端:浏览器或 SDK 若不按 SSE 解析,也会等到流结束才渲染。
说明: 响应沿 Bedrock → Lambda → API Gateway → CloudFront → Client 回流,其中 API Gateway、CloudFront 与客户端是最容易被忽略的三处缓冲。任意一处把 chunk 攒起来,前端表现就是“转圈很久后一次性刷出”。
3.2 API Gateway 的流式开关
REST API 支持把响应传输模式设为 STREAM,从而不必等后端算完就开始下发:
x-amazon-apigateway-integration:
httpMethod: "POST"
type: "aws_proxy"
timeoutInMillis: 300000
responseTransferMode: "STREAM"使用该模式必须知道的边界(以官方文档为准):
- 仅 REST API 支持,HTTP API 与 WebSocket API 不支持;且仅适用于
HTTP_PROXY/AWS_PROXY集成; - 流式最长可达 15 分钟,但仍受空闲超时约束:区域端点和私有端点约 5 分钟,边缘优化端点仅 30 秒——边缘优化 + 流式是一个极易踩的坑;
- 启用后不再支持端点缓存、内容编码与 VTL 响应转换;压缩必须在集成侧自己做;
- 前 10 MB 不限速,超出部分限制在约 2 MB/s;
- 整段流结束后服务端逻辑可能仍在跑,需自行对齐 Lambda 超时。
说明: 两种模式下后端完成生成的时刻完全一致(右侧虚线),差别只在首字节到达的时刻。这正是“流式只改善感知延迟”的含义——它不能让模型变得更快。
3.3 Lambda 侧:函数必须真的“边算边写”
export const handler = awslambda.streamifyResponse(
async (event, responseStream) => {
const stream = awslambda.HttpResponseStream.from(responseStream, {
statusCode: 200,
headers: { "Content-Type": "text/event-stream" }
});
for await (const chunk of bedrockStream()) {
stream.write(chunk); // 逐 chunk 下发,而非累积后返回
}
stream.end();
}
);Lambda 函数超时上限为 15 分钟,与 API Gateway 流式的上限一致,二者需要一起配置。若 Lambda 内部先聚合再返回,那么上游开不开流式都没有意义。
4. 选型决策:五个问题定承载层
按以下顺序自问,答案基本指向唯一解:
- 是否需要自定义权重 / 特定量化 / 自定义算子? 是 → SageMaker 或自建。
- P99 抖动是否写进了 SLA? 是 → 需要独占算力,排除共享池。
- 流量是尖峰波动还是长期稳定? 波动 → 按 token 计费的无服务器形态;长期稳定高负载 → 常驻实例的单位成本更优。
- 主延迟指标是 TTFT 还是 TPOT? TTFT 敏感(短输出、长输入)→ 优先优化 prompt 长度与前缀缓存;TPOT 敏感(长输出)→ 优先优化显存带宽与量化。
- 是否有数据不出 VPC / 不出区域的硬性合规要求? 有 → 需要能明确落到 VPC 与指定区域的承载形态,并把跨区域路由从预算里剔除。
5. 反模式与边界(Trade-offs)
常见反模式:
- 把流式当成性能优化。 它只改善感知延迟,不改变总时长;真正的优化是缩短 prompt、提高缓存命中率、降低 KV Cache 占用。
- 在 Lambda 与模型之间多加一层“纯转发”。 每一次跳转都叠加冷启动、序列化与网络 RTT。若只为加鉴权,应评估是否能让客户端直连(例如通过签名请求),把 Lambda 只用于必须编排的场景。
- 忽略 29 秒集成超时与边缘端点 30 秒空闲超时。 这两条是生成式应用线上 504 与“流到一半断开”最常见的根因。
- 用同步 HTTP 承载 Agent 长循环。 多轮工具调用的总时长很容易超过任何同步网关的上限,应改为异步任务 + 回调 / 轮询结果。
Bedrock 的反指征:
- 需要独占 GPU 以获得可预测 P99;
- 需要自定义推理引擎、算子或特殊量化方案;
- 需要把模型权重留在自建体系内并完全掌控生命周期。
SageMaker / 自建的反指征:
- 流量稀疏且不可预测(常驻实例在闲置时段是纯成本);
- 团队不具备 GPU 运维与推理引擎调优能力——把控制权拿在手里却用不好,结果通常比托管更慢也更贵。



