跳到正文
原文
Hugging Face Blog·· 2026-07-07精选AI 评分62

SkyPilot 与 Hugging Face 打通:用 hf:// 挂载实现零出站存储

Run AI workloads on any cloud, store on HF Mirror: zero-egress storage with SkyPilot

AI 导读

Hugging Face 与 SkyPilot 联合推出 hf:// 挂载能力,可将 Hugging Face Bucket 或模型、数据集仓库挂载进 SkyPilot 任务,在 20 多个云、Kubernetes、Slurm 和本地环境中运行 GPU 作业。

推荐理由

原文给出了 hf:// 挂载方式和跨云零出站读取的实测吞吐数据,读者可据此判断多云端 GPU 训练的存储成本变化。

正文 · AI 翻译

对大多数团队来说,模型和数据集都存放在某一朵云某个区域的一个存储桶里。而你能拿到的 GPU——无论是用于开发、训练还是推理——却越来越多地坐在与数据不同的另一朵云上。一旦两者分离,仅仅为了把自己的数据读到自己的 GPU 上,你就要支付一笔跨云传输税。

我们与 HF Mirror 携手,把这两半合到了一起:你的模型和数据集留在 Hub 上,SkyPilot 则在任何拥有 GPU 的集群上运行计算(开发、训练或推理)。用一个 hf:// URL 和你已有的 HF_TOKEN,就能把 HF Mirror Bucket 或任意 Hub 仓库挂载进 SkyPilot 任务,然后在任何有容量的地方启动它。HF Mirror 不收取出口流量费,因此在任何云上,把你的数据读到这些 GPU 上都不花一分钱。

以下是新增内容:

  • 你的 Hub 数据可用于任意任务。 store: hf 可以通过 MOUNT 或 COPY,用一个 hf:// URL 和你现有的 HF_TOKEN,把 HF Mirror Bucket(读写)或任意 模型 / 数据集 / Space 仓库(只读)挂载进 SkyPilot 任务。
  • 在任何云、任何 GPU 上运行。 SkyPilot 会在 20 多朵云、Kubernetes、Slurm 和本地环境中寻找该任务的计算资源,因此同一次运行会使用你预留或按需的、任何厂商的可用 GPU。
  • 读取数据零出口流量。 HF Mirror Storage 不收取出口流量或 CDN 费用,因此无论 SkyPilot 把任务落在哪里,它都直接从同一个存储桶读取你的模型和数据集,无需按云复制,也没有拉取数据的出口流量账单。
  • 基于 Xet 的去重。 Bucket 构建在 Xet 之上,因此增量检查点和模型变体只存储和传输发生变化的那些数据块。
  • 共同打造。 HF Mirror 和 SkyPilot 联合发布了这一功能,HF Mirror 团队还将 hf-mount 的 FUSE 修复上游化,使其能在非特权容器中工作。

HF Mirror Storage 现已成为 SkyPilot 的一等后端

SkyPilot mounts HF Mirror models, datasets, and checkpoints into jobs running on reserved GPU clusters across CoreWeave, Nebius, GCP, and 20+ more, with zero-egress reads.

SkyPilot 任务早已能通过把云对象存储(S3、GCS、Azure、R2 等众多存储)挂载到本地路径来读写它们。HF Mirror Storage 现在也以 store: hf 的身份加入这一行列,通过 hf:// 协议访问:

file_mounts:
  # A HF Mirror Bucket, read-write, for checkpoints, logs, processed data.
  /checkpoints:
    source: hf://buckets/my-org/qwen-sft
    store: hf
    mode: MOUNT # or COPY
  # A model repo, mounted read-only.
  /base-model:
    source: hf://Qwen/Qwen3.5-4B
    store: hf
    mode: MOUNT
  # A dataset repo, pinned to a revision, read-only.
  /data:
    source: hf://datasets/my-org/my-dataset@main
    store: hf
    mode: MOUNT

这一个 hf:// 协议覆盖了整个生命周期:从仓库中读取模型和数据集,在训练时把检查点写入 Bucket,把训练完成的模型发布回仓库,并在推理时将其拉取到推理服务器上。大多数团队已经把模型和数据集放在 Hub 上,因此无需迁移步骤,也无需创建新的存储账户。

MOUNT 使用 HF Mirror 的 hf-mount FUSE 后端,因此一个 bucket 或仓库会作为本地路径出现在 SkyPilot 的其他 FUSE 挂载点(gcsfuse、blobfuse2、rclone、goofys)旁边。数据获取发生在文件系统层:当你的代码发起 read() 时,驱动只从 Xet 后端拉取那些字节,因此只有你实际访问的数据才会经过网络,而 hf-mount 会保留一份磁盘缓存,使重复读取保持在本地。这种磁盘缓存正是 SkyPilot 在 MOUNT_CACHED 下为其其他后端提供的行为,在那里普通的 MOUNT 会改为每次读取都从 bucket 流式获取,不在本地保留任何内容。对于 hf 存储,MOUNT 和 MOUNT_CACHED 行为相同,因此两种模式都会保留缓存。

由于读取是惰性的,进程可以在整个文件下载完成之前就开始处理大型文件,而不是先阻塞等待完整副本。这让 GPU 几乎立即开始工作,在数据流入时边流边训练,而不是在数据集或检查点下载期间空转(并计费)。这在第一个 epoch 收益最大,因为此时还没有任何缓存。COPY 走的是另一条路线,通过 huggingface_hub 预先下载,没有任何特殊要求。

认证用的就是你已经持有的 token。在环境中设置 HF_TOKEN,并通过 --secret HF_TOKEN 把它交给运行;无论任务落在哪个云上,SkyPilot 都用它来做挂载。一个 token 就能通用,不管任务落在 AWS、GCP、Azure、Nebius、Lambda 还是你自己的 Kubernetes 集群上,所以无需在多个云之间管理各自的存储桶密钥。

无出口流量费:存储不再决定你在哪里运行

GPU 容量如今很少来自单一来源。为了获得足够的 H100 和 H200,团队会同时在多个供应商处持有预留和承诺容量(在超大规模云上的一块配额、在新云上的一个集群,也许还有本地机架),并在有分配的地方运行。SkyPilot 正是为此而生:一份作业规格,调度到 20 多个云、Kubernetes 和本地环境,落在任何空闲的预留集群上。

对象存储一直是难点。对象存储是按区域和按云划分的,因此要为一个位于不同供应商数据中心的 GPU 或推理服务器供数据,要么在每个供应商的存储桶里都保留一份数据副本,要么付费跨云拉取。大多数云在数据离开其网络的那一刻就收取出口流量费(AWS 约 $0.09/GB),而且常常在同一云内的区域之间也收费。把基础模型拉到每个推理节点上,或者从另一个云上的集群对数据集迭代多个 epoch,都会在你已经预留的 GPU 之上叠加一笔高额账单。团队最终只能把每次运行固定到持有数据的那个供应商,让其余容量闲置。

HF Mirror Storage 在成本最要命的地方——读取侧——消除了这笔开销。凭借 无出口流量费或 CDN 费用 以及 $12-18/TB/月的存储价格(相比之下 AWS S3 约为 $23/TB 外加出口流量费),同一个存储桶可以从上述所有集群访问,而且无论 GPU 在哪里运行,读取都是免费的。回写仍然要付你计算云通常的出口流量费,与写到任何云外存储一样,但对大多数 AI 工作负载来说,读取占主导:数据集被流式读取多个 epoch,或者模型权重被拉到每个新的训练或推理节点。于是你不再需要把每次运行固定到持有数据副本的那个供应商。

一个快速基准测试

为了收集一些基准数据,我们跑了一个小型微调:在 HuggingFaceH4/Multilingual-Thinking 数据集上用 TRL 的 SFTTrainer 微调 Qwen/Qwen3.5-4B,从模型的 Hub 仓库以只读方式挂载模型,并把每个检查点写入 HF Mirror Bucket。同一份 SkyPilot YAML 在 AWS、GCP 和 Lambda 上运行,只更改 --infra。SkyPilot 把每个作业放在有免费 GPU 的地方,三者都读写同一个存储桶。

# qwen-sft.yaml. Launch anywhere: sky launch qwen-sft.yaml --infra aws|gcp|...
resources:
  accelerators: H100:1 # or whatever the cloud has

file_mounts:
  /base-model:
    source: hf://Qwen/Qwen3.5-4B # read-only, lazy-mounted from the Hub
    store: hf
    mode: MOUNT
  /checkpoints:
    source: hf://buckets/my-org/qwen-sft # read-write Bucket
    store: hf
    mode: MOUNT

run: |
  python train.py --model /base-model --output_dir /checkpoints

我们测量的结果:

  • 模型在每个云上都免费加载。惰性读取只拉取 from_pretrained 触及的内容,所以大约 30 秒就准备好开始训练(最高约 ~500 MB/s)。由于 HF Mirror 不收取出口流量费,这次拉取零成本;如果模型存放在 S3 中,那么对另一个云上 GPU 的每次读取都会被收取出口流量费(AWS 上约 $0.09/GB)。
  • 检查点直接流式传输到存储桶,速度高达约 170 MB/s(每个权重 8.43 GB),并在 GPU 实例结束后持久保存。

各云平台的检查点写入存储桶速度如下:

云平台 GPU 检查点写入速度
AWS (us-east-2) L40S ~168 MB/s
GCP (us-central1) L4 ~123 MB/s
Lambda (us-west-3) H100 ~112 MB/s

Xet 支持的存储:检查点和模型变体的去重

HF Mirror Buckets 基于 Xet 构建,它使用内容定义分块将文件拆分为约 64 KB 的块,每个唯一块只存储一次。由于边界跟随内容,编辑只会改变它触及的块,其余块会被识别为已存储。这在几个方面带来了收益:

  • 增量检查点和适配器检查点。当你冻结层、训练适配器,或在两次保存之间让大部分权重保持不变时,只有发生变化的块会被上传,而不是整个检查点。
  • 共享基础模型的变体。一个基础模型的微调和量化版本之间大量重叠,因此共享的块在所有版本中只存储一次。
  • 追加写入的数据集。对话轨迹或推理输出等日志通过向大型 Parquet 文件追加行来增长。已有的行组保持字节完全一致,因此只有新行会被传输:在 HF Mirror 的测试中,向一个 10 万行的表追加 1 万行只传输了约 10 MB,而不是完整的约 106 MB。(如果你就地编辑或删除行,请使用 use_content_defined_chunking=True 写入以保持变更局部化。)
  • 重新上传会跳过已存储的内容。在我们的测试中,重新上传一个已在存储桶中的 8.43 GB 数据块大约用了 8 秒,而首次上传用了 24 秒,因为只有块哈希需要传输。同样的机制让服务器端的hf buckets cp在仓库和存储桶之间按引用复制,而不是重新上传字节。

节省多少取决于你的工件重叠程度,但去重是自动的:你照常写入检查点,只有新的块会离开机器。

开始使用

pip install "skypilot[huggingface]"
hf auth login  # or: export HF_TOKEN=<your-token>

向任意 SkyPilot 任务添加 hf:// 挂载并启动。MOUNT 需要带有 glibc 2.34+ 和 /dev/fuse 的基础镜像。

共同构建:HF Mirror 与 SkyPilot

最初的 store: hf 支持源于 Nikhil Jha 的贡献。HF Mirror 团队将其推进,并向上游提交了 hf-mount FUSE 修复,使其能够在非特权容器中挂载,这是许多 Kubernetes 集群的默认配置。SkyPilot 团队将其接入存储后端。整条路径都是开源的:SkyPilot、HF Mirror 的 hf-mount 以及 huggingface_hub 客户端。

资源

来源:Hugging Face Blog · hf-mirror.com