GEOZ

把 Gemma 4 塞进 T4 小实例:单请求只慢两成,并发一上来性价比就翻车

2026/10/1
把 Gemma 4 塞进 T4 小实例:单请求只慢两成,并发一上来性价比就翻车

AIAI Summary (BLUF)

本文是系列教程的第四部分,指导如何在 Amazon SageMaker 最小的 GPU 实例(NVIDIA T4)上部署 Gemma 4 模型。通过打补丁解决 Turing 架构的共享内存限制,并使用 MCP 工具简化 vLLM 部署管理。实测显示 T4 的解码速度是 L4 的 0.77 到 0.82 倍,但答案完全一致,且 12B 是能容纳的最大版本。

核心洞察

这篇文章最有意思的地方在于,它证明了在云上跑大模型推理,最便宜的 GPU 不一定是最省钱的选择。作者把 Gemma 4 塞进了 SageMaker 上最小的 T4 实例,单用户场景下性能只比 L4 慢两成,但一旦并发上来,性价比就翻车了。如果你正在纠结选哪个实例,文末那张对照表值得先看。


这篇文章把 Gemma 4 部署到 Amazon SageMaker 提供的最小 GPU 上,也就是 NVIDIA T4,然后拿它跟之前几篇里的 L4 做对比。同时构建了一套 Python MCP 工具,用来简化 vLLM 托管部署的管理。

代码仓库地址:https://github.com/xbill9/sagemaker-gemma

模型 Gemma 4 E2B、E4B、12B 和 26B A4B,4-bit 权重加 4-bit 嵌入
硬件 SageMaker ml.g4dn.xlarge,1 块 NVIDIA T4,16 GB;对比 ml.g6.xlarge,1 块 L4
区域 us-east-2
软件 AWS vLLM SageMaker 容器 0.30.0,带 Turing attention 补丁
结果 T4 解码速度是 L4 的 0.77 到 0.82 倍,回答完全一致;12B 是能塞进去的最大模型

核心结论

  1. Gemma 4 的 E2B、E4B 和 12B 三个版本可以在 SageMaker 最小的 GPU(ml.g4dn.xlarge,单块 16 GB NVIDIA T4)上服务,且 40 个测试问题的答案与 L4 逐字节完全一致。

  2. 单请求解码速度上,T4 是 L4 的 0.77 到 0.82 倍(E2B 108.5 tok/s、E4B 65.6 tok/s、12B 28.5 tok/s);但 16 路并发时 T4 只有 L4 的 0.53 到 0.63 倍。

  3. 按 16 路并发计算每百万输出 token 成本,T4 比 L4 贵 5%(E2B,$0.260 对 $0.249)到 24%(12B,$0.945 对 $0.760),因为 T4 小时价格是 L4 的 0.65 倍,但负载下吞吐量只有 0.53 到 0.63 倍。

  4. 26B A4B 无法在单块 T4 上运行:权重加载成功后引擎因内存不足(OOM)失败,12B 是单块 T4 能服务的最大模型,其 KV 缓存仅够 20,354 个 token,约 2.48 个满 8,192 token 上下文的请求。

  5. 在 ml.g4dn 上运行 CUDA 13 的 vLLM 0.30.0 容器,必须将 InferenceAmiVersion 设为驱动 580 的主机镜像(al2023-ami-sagemaker-inference-gpu-4-1),否则端点会在 Creating 状态约六分钟后以 CannotStartContainerError 失败且不产生 CloudWatch 日志组。

从哪里开始

这是系列文章的第四篇。第一篇用 aws CLI 和 MCP 服务器把 Gemma 4 部署到 SageMaker 端点:https://dev.to/aws-builders/gemma-4-on-an-amazon-sagemaker-endpoint-aws-cli-nvidia-l4-and-an-mcp-server-2c9d

第二篇对比了 Google 的 QAT 检查点和全尺寸 bf16 版本:https://dev.to/aws-builders/gemma-4-on-amazon-sagemaker-qat-weights-decode-205x-faster-than-bf16-on-one-l4-318m

第三篇用 4-bit 嵌入重新打包了 QAT 权重:https://dev.to/aws-builders/gemma-4-on-amazon-sagemaker-4-bit-embeddings-decode-up-to-139x-faster-on-one-l4-36mf

这篇把第三篇的构建往下推了一代 GPU。


这件事在生态里的位置

SageMaker JumpStart 上 Gemma 4 的起步实例是 ml.g6e.xlarge,一块 NVIDIA L40S,只支持 E2B;12B 更是要 ml.g6e.16xlarge 才能跑。JumpStart 里没有任何一个 Gemma 4 条目列了 T4。Gemma 4 在 Turing GPU 上的支持是 vLLM 的一个未关闭 issue,编号 38918,标题是 “Gemma4 on Turing GPUs (SM 7.5): all attention backends hit shared memory limits”,九月有人在 vLLM 0.29.0 上又报了一次。这里部署的构建,是作者对 Hugging Face 上 Google QAT 权重的重新打包版本,带 4-bit 嵌入。

26B A4B 这个构建是该模型第一个把 Google QAT 权重保持在 4-bit 网格上的 W4A16 检查点。在第 0 层的 query 投影里,11,534,336 个权重没有一个改变量化级别;而六月发布的同一个 QAT 导出的 AWQ 版本,有 30.3% 的权重至少跳了一整级。grid_check.py 通过 HTTP 从每个检查点读取那一个张量然后做对比。


到这一步你应该已经准备好了

  • 仓库已经克隆,make test 通过
  • 有一个 aws login 会话,账号对 ml.g4dn.xlarge 有 SageMaker 端点配额
  • 第三篇在 L4 上的测量数据,这篇文章要拿来做对比

SageMaker 上最小的 GPU 是什么

项目的 MCP 服务器有个 check_quotas 工具,能读取账号在每个美国区域对各实例类型的端点配额:

| 实例 | us-east-1 | us-east-2 | us-west-1 | us-west-2 |
| `ml.g4dn.xlarge` | 2 | 2 | 2 | 2 |
| `ml.g5g.xlarge` | - | - | - | - |
| `ml.g5.xlarge` | 2 | 2 | - | 2 |
| `ml.g6.xlarge` | 1 | 1 | - | 1 |
| `ml.inf2.xlarge` | 0 | 2 | - | 0 |

横杠表示 SageMaker 对这个类型没有配额条目。ml.g4dn.xlarge,一块 16 GB 的 T4,是能拿到的最小 GPU。Graviton T4G(g5g)只在 EC2 上有。Inferentia2 虽然列出来了,但它跑的是 Neuron SDK,需要不同的容器和编译好的模型。


第一步:给容器打 Turing 补丁

Gemma 4 的 full-attention 层宽度是 512。vLLM 用 Triton attention 内核来服务它们,这个内核的 tile 每块需要 98,304 字节的共享内存。T4 是 Turing 架构,上限是 65,536,所以引擎在启动时就挂了:

triton.runtime.errors.OutOfResources: shared memory,
Required: 98304, Hardware limit: 65536

SageMaker 容器里的 vLLM 0.30.0 没有针对这个的修复。作者在 Compute Engine 的 T4 上用一个脚本服务 Gemma 4,把 pre-Ampere GPU 上的 tile 减半,SageMaker 镜像也用了同一个脚本,通过一个 FROM 官方容器的 Dockerfile 构建:

ARG BASE_IMAGE
FROM ${BASE_IMAGE}
COPY patch_triton_turing.py /opt/turing/patch_triton_turing.py
RUN set -eu; \
    target="$(python3 -c 'import importlib.util, os; print(os.path.join(importlib.util.find_spec("vllm").submodule_search_locations[0], "v1/attention/ops/triton_unified_attention.py"))')"; \
    python3 /opt/turing/patch_triton_turing.py "$target"; \
    python3 /opt/turing/patch_triton_turing.py --check "$target"; \
    python3 -c 'import torch, sys; a = torch._C._cuda_getArchFlags(); print("torch arch:", a); sys.exit(0 if "sm_75" in a else 1)'

最后一行会在镜像里的 PyTorch 没有 Turing 内核时直接拒绝构建。CodeBuild 负责构建镜像并推送到私有 ECR 仓库,所以 8 GB 的基础镜像根本不会碰到本地磁盘:

#8 1.092 patch_triton_turing: patched /usr/local/lib/python3.12/dist-packages/vllm/v1/attention/ops/triton_unified_attention.py
#8 1.092   smem budget   : 60000 B of Turing's 65536 hard limit
#8 5.652 torch arch: sm_75 sm_80 sm_86 sm_90 sm_100 sm_120

这个补丁在 L4 或更新的卡上是空操作,镜像保留了官方 entrypoint,所以所有 SM_VLLM_* 设置照常工作。Dockerfile 和 buildspec.yml 都在仓库的 turing 目录里。


第二步:选主机镜像

SageMaker 生产变体跑在几种主机镜像之一上,每种有自己的 NVIDIA 驱动,通过 InferenceAmiVersion 选择:

al2-ami-sagemaker-inference-gpu-2      NVIDIA 驱动 535, CUDA 12.2
al2-ami-sagemaker-inference-gpu-3-1    NVIDIA 驱动 550, CUDA 12.4
al2023-ami-sagemaker-inference-gpu-4-1 NVIDIA 驱动 580, CUDA 13.0

vLLM 0.30.0 容器是基于 CUDA 13 构建的:

NVIDIA_REQUIRE_CUDA=cuda>=13.0 ...
CUDA_VERSION=13.0.2

sm.py 从 .env 里传入主机镜像:

INFERENCE_AMI_VERSION=al2023-ami-sagemaker-inference-gpu-4-1

提示:没有日志组说明容器根本没启动

不设置 InferenceAmiVersion 的话,用这个镜像的 ml.g4dn.xlarge 端点会在 Creating 状态大约六分钟后失败:

CannotStartContainerError. Please ensure the model container for variant AllTraffic starts correctly when invoked with 'docker run <image> serve'

而且完全没有 CloudWatch 日志组。日志组缺失说明问题出在主机层面,镜像里的代码还没跑到:对比容器的 NVIDIA_REQUIRE_CUDA 和主机镜像的驱动版本。加上上面的设置后,同一个镜像在同一个实例类型上 13.2 分钟就到达 InService。


第三步:跑一轮测试

这轮测试服务的是第三篇的纯文本构建加 4-bit 嵌入,一次一个端点:部署、测量、拆除。除了数据类型之外,设置跟 L4 那轮一致,因为 Turing 不支持 bf16:

IMAGE_URI=<account>.dkr.ecr.us-east-2.amazonaws.com/sagemaker-gemma-vllm:0.30.0-sagemaker-v1.3-sm75
INFERENCE_AMI_VERSION=al2023-ami-sagemaker-inference-gpu-4-1
INSTANCE_POOLS=ml.g4dn.xlarge,ml.g4dn.2xlarge
MAX_MODEL_LEN=8192
SM_VLLM_DTYPE=float16

每个端点从部署调用到 InService 用了 13.3 分钟。然后 compare.py 测量单请求解码、1 到 16 路并发请求,以及温度设为 0 时的 40 个问题,跟第二篇和第三篇一样。compare.py combine 把每个 T4 运行跟对应的 L4 运行并排放:

decode_tokens_per_second              35.0                28.5  0.81
load_c16_tokens_per_second           411.8              216.45  0.53
quality_correct                         40                  40
identical answers: 40/40

T4 对 L4:速度

模型 解码,T4 (tok/s) 解码,L4 (tok/s) T4 / L4 16 并发,T4 / L4
E2B 108.5 141.7 0.77 0.63
E4B 65.6 79.9 0.82 0.57
12B 28.5 35.0 0.81 0.53

单用户场景下,T4 大约是 L4 的 0.8 倍。负载一上来差距就随模型变大而拉大:16 路并发时,T4 在 E2B 上只有 L4 的 0.63 倍,12B 上只有 0.53 倍。

Compute Engine 的 T4 用同样的补丁服务同样的 E2B 构建,解码速度是 109.7 tok/s,这里测出来是 108.5。那台机器跑的是 pip 安装的 vLLM 0.29.0,上下文 16,384 token,所以这个吻合只能算交叉验证,不是受控对比。


回答还正确吗

三个模型在 T4 上给出的 40 个答案跟 L4 上一模一样,逐字节相同:E2B 和 E4B 都是 40 题对 36 题,12B 是 40 题全对。T4 用 fp16 计算,跑的是裁剪过的 attention tile,这两点都没改变任何答案。


引擎分配了多少资源

模型 权重 (GiB) KV 缓存,T4 (tokens) KV 缓存,L4 (tokens)
E2B 2.86 660,033 1,209,977
E4B 4.52 194,336 376,156
12B 7.36 20,354 52,541

权重在两块 GPU 上占的内存一样。T4 留给 KV 缓存的空间更少:12B 只能存 20,354 个 token,也就是 2.48 个满 8,192 token 上下文的请求。


26B 塞不进去

26B A4B 构建在 L4 上占 14.2 GiB 权重。在 T4 上它用了第三篇里 31B 需要的降级设置:内存 0.97,1,024 token 上下文,四个序列。权重加载成功了,然后引擎内存不足:

memory allocation failed with OOM on device 0 while trying to allocate 253755392 bytes (free: 191627264, total: 15636037632).

T4 报告的总量是 14.56 GiB。在所有测试过的构建里,12B 是单块 T4 能服务的最大模型。


性价比怎么样

SageMaker 在 us-east-2 的按需托管价格,来自 2026-09-30 的 AWS Price List API,ml.g4dn.xlarge 是每小时 $0.736,ml.g6.xlarge 是 $1.1267。按 16 路并发计算每百万输出 token 的成本:

模型 T4 L4 T4 / L4
E2B $0.260 $0.249 1.05
E4B $0.419 $0.369 1.14
12B $0.945 $0.760 1.24

T4 每小时价格是 L4 的 0.65 倍,负载下吞吐量是它的 0.53 到 0.63 倍,所以繁忙的 T4 每 token 成本更高,E2B 上贵 5%,12B 上贵 24%。而大部分时间空闲的端点按小时计费,这时候 T4 只要 0.65 倍。


提示:原型阶段把健康检查超时调低

sm.py 把 ContainerStartupHealthCheckTimeoutInSeconds 设成 1800,给大模型下载和加载留足时间。启动就崩溃的容器会让端点在 Creating 状态卡满整个窗口:26B 端点在 15:33 内存不足,15:59 才被标记为 Failed,距离进入 Creating 过了 36.5 分钟。对于两分钟内就能加载完的小模型,几百秒就够了,启动失败也能更快返回。


那到底选哪个

工作负载 GPU 原因
E2B 或 E4B,低流量 T4 小时价格 0.65 倍,单用户速度 0.8 倍
任意规模,稳定负载 L4 每 token 成本更低,KV 缓存是 1.8 到 2.6 倍
12B L4 12B 在 T4 上只够放 2.48 个满长度请求
26B A4B 和 31B L4 或更大 塞不进一块 T4

怎么让计费停下来

每个端点测量完就删掉了,还有一个看门狗在测试退出时清理所有遗留资源:

2026-09-30T15:59:45Z gemma-4-e2b-emb4-t4: gone
2026-09-30T15:59:46Z gemma-4-e4b-emb4-t4: gone
2026-09-30T15:59:46Z gemma-4-12b-emb4-t4: gone
2026-09-30T15:59:47Z gemma-4-26b-emb4-t4: gone

构建资源空闲时不花钱:一个 ECR 仓库、一个 CodeBuild 项目、它的角色,还有 us-east-2 里的一个源桶。


总结

这篇文章的目标是在 SageMaker 提供的最小 GPU 上服务 Gemma 4,并测量它相对 L4 放弃了什么。解决方案的关键是一个在派生容器里给 vLLM 打的 Turing 补丁,跑在驱动 580 的主机镜像上。T4 的结果是:

  • E2B、E4B 和 12B 能在单块 T4 上服务,给出跟 L4 相同的 40 个答案
  • 单请求解码速度是 L4 的 0.77 到 0.82 倍
  • E2B 解码速度 108.5 tok/s,跟 Compute Engine T4 的 109.7 一致
  • 16 路并发时 T4 只有 L4 的 0.53 到 0.63 倍,每 token 成本高 5% 到 24%
  • CUDA 13 容器在 ml.g4dn 上需要把 InferenceAmiVersion 设成驱动 580 的主机
  • 26B A4B 塞不进一块 T4

范围说明:单账号,us-east-2 的 SageMaker ml.g4dn.xlarge,AWS 容器的 vLLM 0.30.0 加 Turing 补丁,fp16,每个模型一次部署,时间 2026-09-30。L4 数据来自第三篇,2026-09-29 在 bf16 下用官方容器测得。吞吐量通过 aws CLI 从一台客户端机器测量,价格是按需列表价。

用 MCP 做 SageMaker 部署和基准测试的策略,是通过一步步增量验证出来的。


参考资料

常见问题(FAQ)

在 SageMaker 上部署 Gemma 4,最小的 GPU 实例是哪个?

是 ml.g4dn.xlarge,配一块 16 GB 的 NVIDIA T4。Graviton T4G 只在 EC2 上有,Inferentia2 需要 Neuron SDK 和不同容器,所以 T4 是 SageMaker 上能拿到的最小 GPU。

T4 跑 Gemma 4 为什么启动会报共享内存不足?

Gemma 4 的 full-attention 层宽度为 512,vLLM 的 Triton attention 内核每块 tile 需要 98,304 字节共享内存,而 Turing 架构上限只有 65,536,引擎启动即失败,需要打补丁把 tile 减半。

T4 和 L4 跑 Gemma 4 的速度差多少?

实测 T4 的解码速度是 L4 的 0.77 到 0.82 倍,回答内容完全一致。单用户场景只慢两成,但并发上来后性价比会明显下降,12B 是 T4 能容纳的最大版本。

阿凯广州
本文由 阿凯 审核,最后更新于 2026年10月1日
联系编辑 →
← 返回文章列表
分享到:微博

版权与免责声明:本文仅用于信息分享与交流,不构成任何形式的法律、投资、医疗或其他专业建议,也不构成对任何结果的承诺或保证。

文中提及的商标、品牌、Logo、产品名称及相关图片/素材,其权利归各自合法权利人所有。本站内容可能基于公开资料整理,亦可能使用 AI 辅助生成或润色;我们尽力确保准确与合规,但不保证完整性、时效性与适用性,请读者自行甄别并以官方信息为准。

若本文内容或素材涉嫌侵权、隐私不当或存在错误,请相关权利人/当事人联系本站,我们将及时核实并采取删除、修正或下架等处理措施。也请勿在评论或联系信息中提交身份证号、手机号、住址等个人敏感信息。