SageMaker 用镜像按需加载缩短任务启动
Amazon SageMaker AI 为训练和处理任务引入 SOCI 镜像索引,通过按需加载避免启动前下载完整容器镜像。AWS 称容器启动可从分钟级缩短至秒级,且无需修改任务定义,文章提供基准与接入说明。
AI 深度解读
深度学习任务还没开始训练,GPU 就已经在计费:十几 GB 的容器镜像要先下载、解压、写盘,实验只能等。AWS 给 SageMaker AI Training 和 Processing 作业引入 SOCI 索引,把完整下载移出了启动的必经路径。
它的办法是先取启动需要的文件,其余文件按需加载。AWS 实测中,容器就绪时间降到 3–11 秒,但训练首个 epoch 会付出额外读取成本。对频繁跑短任务的团队,这项优化值得研究;判断收益时,要看整个作业提前多久结束。
为什么几十 GB 的镜像也能几秒启动
传统流程要求 SageMaker AI 从 Amazon ECR 下载完整镜像,然后解压并把每一层写入磁盘。深度学习镜像经常超过 10 GB,这段等待不产生模型训练进度,却属于计费作业时间。几百个超参数搜索任务反复启动时,固定开销会不断累积。
Seekable OCI(SOCI)是一种开源的容器镜像懒加载技术。它用索引记录镜像内部文件的位置,让运行时先获取启动所需的内容,代码执行期间再按需读取其他文件。
它缩短的是代码开始执行前的等待,后续首次访问文件时仍可能等待下载。
索引作为独立的 OCI 制品存入 Amazon ECR,与原镜像关联,因此原镜像的 digest 和已有签名保持有效。SageMaker AI 会自动检查索引,需要时退回标准下载。
不过,兼容性还要单独检查:SOCI 镜像使用基于 containerd 的运行时。入口脚本如果调用 Docker CLI、读取 /var/run/docker.sock,或从 cgroup 路径推导标识,仍可能出问题。服务会挂载 /.dockerenv 兼容标记,原文也明确建议不要新增对它的依赖。
快几十倍的是启动阶段,整个任务省多少
AWS 测了 8 个压缩后为 1.8–35.4 GB 的镜像,覆盖 us-west-2 和 us-east-1,结果取重复运行的中位数。实例包括 ml.g4dn、ml.g5、ml.g6、ml.g6e、ml.g7、ml.g7e、ml.p4d、ml.p5 和 ml.m7i,规格从 xlarge 到 48xlarge。
标准下载耗时从 1.8 GB 镜像的 48 秒,增长到 35.4 GB 镜像的 7 分 17 秒;懒加载保持在 3–11 秒。原文图表描述给出约 10 倍到超过 35 倍,正文另给出 8–46 倍的范围,两处没有进一步解释口径差异。
固定使用 13.2 GB 镜像,在 13 种实例类型和规格组合上,标准下载需要 3 分 16 秒至 4 分 20 秒,懒加载只需 6–8 秒,文中概括为约 34 倍提速。镜像越大,原来必须提前完成的工作越多,节省的时间通常越明显。
训练测试覆盖两类任务:
- ResNet-50 在 Imagenette 的 9,469 张图片上训练,分别使用 13.2 GB PyTorch DLC 和 9.9 GB TensorFlow DLC,实例包括
ml.p5.48xlarge、ml.p4d.24xlarge、ml.g7e.48xlarge、ml.g7.48xlarge,以及ml.g6e.12xlarge、ml.g6e.24xlarge、ml.g6e.48xlarge。 - 用 Hugging Face Trainer,对 Qwen2.5-0.5B 做全参数监督微调(SFT),数据为 alpaca-cleaned 的 51,760 条样本,使用 9.4 GB Hugging Face PyTorch DLC,实例为
ml.p5.48xlarge、ml.p4d.24xlarge和ml.g6.48xlarge。
结果是首个 epoch 多花 3–16 秒,从第二个 epoch 开始,耗时差异处于运行波动范围内。扣除首次读取成本,每个作业最终提前 1–6 分钟结束。开头提到的 GPU 拉取等待时间最多减少 90%,也只对应镜像拉取阶段。
启动时要做更多工作的测试仍有收益:torch.compile 和即时编译(JIT)的 CUDA 扩展,让首个 epoch 增加 7–15 秒,净节省仍有 3 分 25 秒至 3 分 56 秒。镜像内置 6 GB 模型时,加载权重增加 2–3.5 分钟,整个作业仍提前 2–2.5 分钟结束。
但如果入口程序先扫描、校验或预加载大部分镜像内容,懒加载就很难绕过这些读取。原文也承认,此时净收益可能很小。
接入时真正要改的是镜像引用和索引流程
最省事的方式是使用带 -soci 标签后缀的 AWS Deep Learning Container,例如 pytorch-training:2.9-gpu-py312-cu130-ubuntu22.04-sagemaker-v1-soci。原文列出的预索引系列包括 PyTorch Training、TensorFlow Training、vLLM 和 SGLang,部分框架还有 arm64 版本。
已有作业只需替换镜像引用,不用修改入口、数据通道或 API。SageMaker Python SDK 示例仍使用 sagemaker.train.ModelTrainer、sagemaker.train.configs.Compute 和 trainer.train(),通过 training_image 指向 my-training-image:v1.0-soci;示例计算配置为 instance_type="ml.g5.12xlarge"、instance_count=2。
自定义镜像需要在 Linux 主机上生成索引,例如 Amazon Linux 2023,安装 containerd、SOCI snapshotter,以及 Finch 或 nerdctl。原文安装命令为 sudo dnf install -y containerd fuse soci-snapshotter runfinch-finch,然后执行 sudo systemctl start soci-snapshotter 和 sudo systemctl restart containerd。
完成 ECR 登录并拉取原镜像后,下面的命令生成关联索引的镜像引用:
sudo nerdctl image convert --soci \
"$REGISTRY/$REPOSITORY_NAME:$ORIGINAL_IMAGE_TAG" \
"$REGISTRY/$REPOSITORY_NAME:$SOCI_IMAGE_TAG"
关键是 --soci。原文将原标签设为 v1.0,新标签设为 v1.0-soci,再用 sudo nerdctl push --platform linux/amd64 推送新引用。仓库中会新增 SOCI 索引,以及关联镜像与索引的 OCI image index manifest。
标签名字带有 -soci,并不能证明索引已经存在。
启动前可以检查标签对应的 manifest:
aws ecr batch-get-image \
--repository-name "$REPOSITORY_NAME" \
--image-ids imageTag="$SOCI_IMAGE_TAG" \
--accepted-media-types \
"application/vnd.oci.image.index.v1+json" \
--query 'images[0].imageManifest' --output text \
| jq '.manifests[] | {mediaType, artifactType}'
注意输出中的 artifactType:除了平台 manifest,还应存在以 application/vnd.amazon.soci.index. 开头的子 manifest。
另外,从 DLC 执行 FROM 构建出的最终镜像必须重新建索引,基础镜像的索引不会自动继承。需要持续生成时,可以部署 CFN ECR SOCI Index Builder,由 Amazon EventBridge 监听 ECR 镜像推送事件触发处理。
我的判断
这项优化抓住了一个明确的问题:训练任务反复启动,却总要为暂时用不到的镜像内容等待。AWS 同时测了容器就绪时间和完整训练,至少没有只拿启动数字推导最终收益。
但标题式的「训练性能不受影响」需要补上条件:首个 epoch 有代价,后续 epoch 才在测试中表现相当。样本也只有两类训练工作负载,不能直接推断所有 Processing 作业或更大模型都会得到相同结果。原文没有给出重复次数、离散程度和完整成本账单,费用下降有时间依据,具体能省多少钱仍需自己测。
相比精简镜像,SOCI 更适合处理「镜像很大,但启动只访问一部分内容」的情况。精简镜像则直接减少存储和传输内容,两种做法可以一起用。原文没有给出二者的对照数据,不能据此判断哪种投入更划算。
适用范围也很明确:仅支持 Amazon ECR 私有仓库;其他 registry,以及 TrainingRepositoryAccessMode 设为 Vpc 的私有 Docker registry 拉取方式,不符合懒加载条件。原文称功能覆盖所有 AWS Regions,但约 4 GB 以下镜像的收益相对较小。这不是普通 Node 服务改个标签就能获得的通用加速开关。
能拿来做什么
- 如果你维护 SageMaker 训练或数据处理任务,先挑镜像较大、运行较短、启动频繁的一类作业做对照,同时记录容器就绪、首个 epoch 和整个作业耗时。
- 如果团队使用官方 DLC,可以先切换对应的
-soci版本验证;如果用自定义镜像,就为最终构建产物生成索引,并检查 manifest,避免只改标签。 - 在入口脚本中检查全量扫描、校验、预加载,以及 Docker CLI 和 socket 依赖。这些行为分别影响懒加载收益与运行时兼容性。
- 对频繁发布训练镜像的团队,可以评估 EventBridge 自动建索引,并按原文建议用 Finch 在 containerd 环境中提前验证镜像。