[控场AI]
· 15 分钟阅读· 7,669 字

一个Agent跑通AWS六大推理后端:精度、带宽与成本实测

一个Agent跑通AWS六大推理后端:精度、带宽与成本实测

同一Gemma 4模型在AWS六种推理后端上实测:精度、带宽与引擎效率如何决定速度与成本。

本文用同一个Strands Agent将同一问题发给AWS六种推理后端——Bedrock、SageMaker、EC2 g6和g5g上的vLLM,以及手工移植到Inferentia2和Trainium的Gemma 4。实验围绕三个变量展开:权重用多少比特存储、芯片能以多快读出权重、推理引擎能把芯片用到多满。核心发现包括:QAT检查点转int4后精度仅比bf16低不到0.5个点,而bf16直接round的int8反而掉1.3个点;int4 embedding表将E2B从6.32 GiB压到2.85 GiB;g6上的vLLM解码最快,单请求131.9 tok/s、每百万输出Token $1.69;Inferentia2和Trainium带宽是L4的2.0-2.7倍,速度却只有0.28倍,差距全在软件栈;SageMaker与g6同GPU同权重,但每请求多约0.24秒托管开销,每Token成本约为g6两倍。所有支持工具调用的后端12/12次都选了正确过滤条件。

一个Agent跑通AWS六大推理后端:精度、带宽与成本实测

同一个模型,同样的权重,在AWS不同推理后端上却跑出36到132 tokens/s的差距——而小时价格几乎解释不了这个差距。这篇源自"Inference on AWS"演讲的配套文章,用同一个Strands Agent把同一个问题发给六种后端:Amazon Bedrock托管API、SageMaker端点、EC2 g6和g5g上的vLLM,以及手工移植到Inferentia2和Trainium上的Gemma 4。

Inference on AWS演讲配图

支撑整场实验分析的只有三个变量:权重用多少比特存储、芯片能以多快速度读出这些权重、推理引擎能把芯片用到多满。

六种后端一览

实验选用了Gemma 4 E2B这个模型,保证跨后端对比的是同一套权重:

后端推理载体模型
Amazon Bedrock托管APIus.amazon.nova-micro-v1:0
SageMaker ml.g6.xlargeAWS vLLM 0.31.0容器量化版Gemma 4 E2B
EC2 g6.xlarge (NVIDIA L4)vLLM 0.30同一量化包
EC2 g5g.2xlarge (Graviton2 + T4G)vLLM 0.27.2rc0,为sm_75打补丁Gemma 4 E2B,fp16
EC2 inf2.xlarge (Inferentia2)手工移植,编译到NeuronGemma 4 E2B
EC2 trn1.2xlarge (Trainium)同一镜像同一构建

四类后端示意图

第一步:精度决定你放弃了什么

量化格式的核心权衡很直白:每权重比特数越少,单Token需要搬运的数据越少,内存和磁盘占用越小。但只有在硬件原生支持该格式时,小格式才能真的变快;否则权重会被"加宽"回16位再计算,精度损失换来的却是更慢的速度。

从3880条测试记录看,真正值得关注的只有两个结果:

第一,来自Google QAT(量化感知训练)检查点的int4构建,精度仅比bf16低不到0.5个点(0.678 vs 0.683);而从bf16直接round出来的int8构建,反而掉了1.3个点。 这说明量化效果的关键不在于位宽,而在于权重是否在训练阶段就"认识"了低精度。

第二,E2B的embedding表占了权重的绝大部分。 把embedding表也压到int4,模型从6.32 GiB直接降到2.85 GiB——这个降幅主要来自embedding表而非Transformer主体。

原生支持则决定了小格式能否转化为速度:

芯片bf16fp8int8int4
NVIDIA L4 (g6/SageMaker)支持支持支持加宽到16位
NVIDIA T4G (g5g)模拟不支持支持加宽到16位
NeuronCore-v2 (inf2/trn1)支持硬件支持,编译器待跟进支持加宽到bf16,每次调用慢27倍

量化感知训练(QAT)与训练后量化(PTQ)的区别:本文提到的关键差异在于权重是否在训练阶段就“认识”低精度。QAT在训练前向传播中插入伪量化节点,让模型在训练时就能感知到权重与激活将被压到int4或int8的舍入误差,梯度会据此调整,因此模型学到的是对量化鲁棒的表示。PTQ则是拿一个已经用bf16训练好的模型,直接对权重做round-to-nearest或更复杂的校准,模型从未针对低精度优化过,舍入误差会直接冲击输出分布。这就解释了为什么QAT int4只掉0.5个点,而bf16直接round出的int8反而掉1.3个点——位宽更小并不必然更差,训练阶段是否参与才是分水岭。

Embedding表为何主导E2B的体积:Gemma 4 E2B的“E”代表effective参数,即每Token实际激活的参数约2B,但词嵌入表需要为整个词表存储完整向量。词表通常有数万到数十万条目,每条目维度数千,因此embedding表可以轻松占据数GiB,远超Transformer主体。把embedding表压到int4后模型从6.32 GiB降到2.85 GiB,正说明瓶颈在词表而非注意力或FFN层。这也意味着量化策略必须优先处理embedding,否则整体压缩收益有限。

第二步:带宽定天花板,引擎决定离天花板多远

生成每个Token都要把全部权重读一遍,所以内存带宽直接决定了单请求Token/s的上限。而推理引擎的效率,决定了实际能跑多接近这个天花板。

后端加速器内存带宽单请求tok/s
g6.xlargeNVIDIA L424 GB300 GB/s131.9
SageMaker ml.g6.xlargeNVIDIA L424 GB300 GB/s96.5
g5g.2xlargeNVIDIA T4G16 GB320 GB/s(实测277)34.9
inf2.xlargeInferentia22×16 GiB~817 GB/s36.5
trn1.2xlargeTrainium2×16 GiB~613 GB/s36.0
BedrockNova Micro未披露未披露130.4

这张表里最反直觉的是Neuron系列:Inferentia2和Trainium的内存带宽是L4的2.0到2.7倍,但解码速度只有L4的0.28倍。 带宽优势被软件栈完全吃掉了。

Neuron的内存是2×16 GiB,每个NeuronCore独享16 GiB。模型要么跨两个核心拆分,要么必须塞进16 GiB——这对E2B这种embedding表占大头的模型是个硬约束。

内存带宽为何决定解码上限:自回归解码每生成一个Token,都需要把全部模型权重从显存读一遍并与当前隐状态做矩阵乘。因此单请求的Token/s上限约等于内存带宽除以模型权重字节数再乘以效率系数。以L4的300 GB/s和6.32 GiB的bf16模型为例,理论上限约47 Token/s;如果权重压到2.85 GiB的int4,理论上限可升到约105 Token/s,而实际测得131.9 Token/s,说明L4的L2缓存和vLLM的批处理/投机解码进一步提升了有效带宽利用率。反过来,Neuron虽然标称817 GB/s,但int4权重在每次矩阵乘前被复制成密集bf16,等于把权重体积放大回16位,带宽优势被这个“加宽”步骤彻底抵消。

“加宽到16位”意味着什么:当硬件或编译器不支持原生int4张量核心时,加载进来的int4权重必须先解包并扩展到bf16或fp16,才能进入矩阵乘单元。这个解包-扩展过程不仅消耗额外算力,还使实际参与运算的数据量回到16位水平,带宽和容量优势荡然而失。T4G的int4加宽到16位、Neuron的int4加宽到bf16,都是同一个机制;而L4的int4虽然也被加宽,但其Ada Lovelace架构对int4有额外的数据路径优化,所以仍能保持较高吞吐,但实测仍不如原生fp8/int8路径。

第三步:托管组合的真实代价

Bedrock按Token计费,Nova Micro的价格是每百万输入Token $0.035、每百万输出Token $0.14。几行代码就能接入:

from strands.models import BedrockModel
model = BedrockModel(model_id="us.amazon.nova-micro-v1:0", region_name="us-east-1")

SageMaker则需要create-model、create-endpoint-config、create-endpoint三次API调用,vLLM参数通过SM_VLLM_*环境变量传入。实测时端点从部署到InService耗时约9分钟。

关键数据来了:SageMaker跑在与g6完全相同的L4 GPU上、加载完全相同的权重,但每个请求多出约0.24秒的托管路径开销——87个Token在g6上耗时0.660秒,在SageMaker上要0.902秒。这个延迟代价最终体现在每Token成本上:SageMaker的$3.24大约是g6的$1.69的两倍。

第四步:vLLM在L4上的最佳表现

g6.xlarge跑vLLM 0.30,开启两个参数就能启用工具调用:

--enable-auto-tool-choice --tool-call-parser gemma4

L4的规格是Ada Lovelace架构、24 GB显存、300 GB/s带宽、BF16张量121 TFLOPS、FP8张量242.5 TFLOPS、72W单槽PCIe。启动后16分钟就绪,单请求解码131.9 Token/s,是五个实例里最快的。

第五步:Arm + CUDA的过去与现在

g5g搭配Graviton2 Arm主机和NVIDIA T4G,AWS称其为"主流云中首个搭载GPU加速的Arm实例"。但在上面跑Gemma 4需要从源码编译vLLM以支持sm_75,还要打共享内存补丁,因为arm64镜像里没有Turing内核。

有意思的是,同样的Arm+GPU组合今年秋天回到了桌面端。NVIDIA在2026年5月31日发布了RTX Spark:

EC2 g5gNVIDIA RTX Spark
CPUGraviton2, Arm20核Grace, Arm
GPUT4G, TuringBlackwell RTX, 6144 CUDA核心
CPU到GPUPCIeNVLink-C2C
内存16 GB GPU + 16 GB主机最高128 GB统一内存

当年g5g上被迫做的aarch64和CUDA构建工作,正是这类机器的运行基础。

sm_75与Turing内核的编译约束:NVIDIA GPU的计算能力用sm_XX表示,T4G基于Turing架构,对应sm_75。vLLM官方预编译的arm64镜像通常只包含较新架构(如sm_80、sm_86、sm_89)的内核,因为云上Arm+GPU实例长期只有g5g这一代。这导致在g5g上必须从源码编译vLLM,并显式指定-gencode arch=compute_75,code=sm_75,否则运行时找不到对应内核会直接报错。共享内存补丁则是因为Turing的共享内存容量与调度特性与Ampere不同,vLLM的某些kernel默认假设了更大的smem,在T4G上会越界或性能骤降。这些历史包袱正好解释了为什么g5g虽然硬件不弱,却只能跑到34.9 Token/s——软件栈没有为它做原生优化。

第六步:Neuron为什么难伺候

Inferentia2和Trainium跑的是同一个手工移植镜像,实测在inf2.xlarge上:

  • 没有vLLM发行版能在Neuron上跑Gemma 4,引擎是手工移植的,不支持工具定义
  • 图是提前编译的,形状固定(总计512 Token,prompt 128),新形状需要约3.9秒编译
  • 内存是2×16 GiB,单个gather超过约4-5 GB会返回零且不报错
  • int4权重在每次矩阵乘法前会被复制成密集bf16,每次调用比纯bf16慢27倍

这就是带宽2-2.7倍却只能跑到0.28倍速度的原因:芯片带宽够,但这个模型的软件栈还没跟上。

第七步:一个Agent统一调度

实验用的Strands Agent问一个简单问题——11个id里有多少个大于等于10——并提供一个count_ids工具来计算。每个支持工具调用的后端跑三次:

bedrock    run 1/3  ok   quoted=8  filters=['id >= 10']  1.19s
g6         run 2/3  ok   quoted=8  filters=['id >= 10']  0.4s
g5g        run 1/3  ok   quoted=8  filters=['id >= 10']  2.35s
sagemaker  run 1/3  ok   quoted=8  filters=['id >= 10']  0.63s

十二次运行全部答对8,并且都发了正确的过滤条件。为什么连过滤条件也要评分?因为错误的过滤条件也会返回一个精确的数字和干净的来源——它看起来是对的。

第二个Agent在Bedrock上把六个后端当成工具调用,返回一个按代码排序的记分牌:

| vLLM on EC2 g6 (L4) | Paris | 0.151 | 13.2 |
| SageMaker endpoint (vLLM, L4) | Paris | 0.426 | 4.7 |
| Amazon Bedrock | Paris | 0.861 | 2.3 |

为什么工具调用评分要看过滤条件而不只看最终答案:在Agent场景中,模型可以选择直接回答,也可以调用工具。如果模型生成了错误的过滤条件(例如id > 10而不是id >= 10),但恰好因为输入数据分布使得结果仍是8,那么外部观察者会看到一个完全正确的数字和一条看似合理的来源。这种“对答案、错过程”极难通过结果校验发现。本实验把过滤条件也纳入评分,是在验证模型是否真正理解了工具语义,而不仅仅是碰巧答对。十二次全部输出id >= 10,说明这些后端上的模型在工具调用格式和语义上均可靠。

第八步:每种后端到底花多少钱

cost.py从AWS Pricing API拉取按需价格并计算:

后端$/小时24×7 $/月$/百万输出Token(单请求)$/百万输出Token(16并发)
EC2 g6.xlarge0.80485881.690.150
SageMaker ml.g6.xlarge1.12678223.240.291
EC2 g5g.2xlarge0.5564064.43未测
EC2 inf2.xlarge0.75825535.77未测
EC2 trn1.2xlarge1.343898110.37未测
Bedrock Nova Micro—空闲时$00.140.14

一个关键判断:g6如果整月运行,成本会超过Bedrock Nova Micro——除非它能7×24小时平均跑到710输出Token/s(按5输入Token对1输出Token计算)。

所以该选哪个?

  • Bedrock:当它的模型够用时首选,什么都不用管,每Token成本最低
  • g6 + vLLM:需要自己的权重时选它,从QAT检查点量化,速度和单价都是实例里最优的
  • SageMaker:跑同一个容器但按托管端点收费,每Token约为g6的两倍
  • g5g:Arm + CUDA路径
  • Inferentia2 / Trainium:等服务栈支持你的模型后才有性价比

核心结论

  • 🟢 QAT权重转int4的精度与bf16差距在0.5个点以内,int4 embedding表把E2B从6.32 GiB压到2.85 GiB
  • 🟢 g6上的vLLM解码最快,单请求131.9 tok/s、每百万输出Token $1.69,16并发时降至$0.150
  • 🟢 所有支持工具调用的后端12/12次都选了正确的过滤条件
  • ⚠️ SageMaker在相同GPU上每请求多约0.24秒,每Token成本约为g6的两倍
  • ⚠️ 带宽是天花板,引擎决定离天花板多远:Neuron带宽是L4的2.0-2.7倍,速度却只有0.28倍
  • ❌ 没有vLLM发行版能在Neuron上服务Gemma 4,这些后端只能跑固定形状、不支持工具调用的手工移植版本

实验范围说明:一次在us-east-2的彩排(g5g和Bedrock在us-east-1),每个后端三次计时请求。内存数据来自单块MI300X,精度数据来自单块TPU v5e。Bedrock跑的是Nova Micro,与其他行的Gemma 4构建不是同一个模型。按需价格来自AWS Pricing API。

方法论的增量验证策略值得借鉴:所有路径都先用E2B小模型跑通——参数、端口转发和工具解析在任何尺寸下都会以相同方式失败,而E2B在Neuron上加载约2分钟,26B接近4分钟。

#AWS推理#Amazon Bedrock#vLLM#Inferentia2#Trainium#SageMaker#模型量化#Strands Agent
分享:

相关推荐