本页面介绍了如何使用关键 Cloud Storage FUSE 功能和配置来提高 Cloud Storage FUSE 性能,以实现最大吞吐量和最佳性能,尤其是在处理人工智能和机器学习 (AI/ML) 工作负载(例如训练、服务和检查点)时。
注意事项
在应用本页中推荐的配置之前,请考虑以下事项:
您可以使用以下三种方法应用此页面中的推荐配置:
仅限 Google Kubernetes Engine:Google Kubernetes Engine YAML 文件示例
确保您运行的是最新版本的 Cloud Storage FUSE。建议的配置应仅应用于 Cloud Storage FUSE 3.0 版或更高版本,以及在 GKE 集群 1.32.2-gke.1297001 版或更高版本上运行的 Cloud Storage FUSE CSI 驱动程序(适用于 Google Kubernetes Engine)。
建议的配置会缓存作业时长的 Cloud Storage 元数据,并且在首次挂载文件系统后不会再进行检查。因此,我们建议文件系统为只读或文件系统语义为写入新文件的应用,这意味着应用始终写入新文件,以获得最佳性能。以下 AI/ML 工作负载属于“写入新内容”型:
检查点功能
培训
服务
jax.jit()
缓存
本页中的推荐配置已针对大规模 Cloud GPU 和 Cloud TPU 大型机器类型进行了验证,这些机器类型具有大量内存和高带宽网络接口。Cloud GPU 和 Cloud TPU 机器类型在主机节点配置中可用的资源(例如 CPU、内存和本地存储)数量方面可能有所不同。这会直接影响以下配置的性能:
A3 Mega - 1.8 TiB 内存,配备 6 TiB LSSD
Cloud TPU v5e - 188 GiB 内存,无 LSSD
Cloud TPU v5p - 448 GiB 内存,无 LSSD
Cloud TPU v6 (Trillium) - 1.5 TiB 内存,无 LSSD
使用启用了分层命名空间的存储桶
始终使用启用了分层命名空间的存储桶。分层命名空间可将数据整理成分层文件系统结构,从而提高存储桶内的操作效率,缩短响应时间,并减少每个操作的列出调用总次数。
分层命名空间的优势包括:
与平面存储桶相比,启用分层命名空间的存储桶可提供高达 8 倍的初始每秒查询次数 (QPS)。分层命名空间支持每秒 40,000 次初始对象读取请求和 8,000 次初始对象写入请求,这远高于典型的 Cloud Storage FUSE 平面存储桶,后者最初仅支持每秒 5,000 次对象读取请求和 1,000 次初始对象写入请求。
分层命名空间提供原子目录重命名,这是使用 Cloud Storage FUSE 进行检查点设置以确保原子性的必要条件。大规模设置检查点时,使用启用了分层命名空间的存储桶尤其有益,因为机器学习框架使用目录重命名来完成检查点,这是一个快速的原子命令,仅在启用了分层命名空间的存储桶中受支持。如果您选择不使用启用了分层命名空间的存储桶,请参阅提高非 HNS 存储桶的重命名限制。
如需了解如何创建启用了分层命名空间的存储桶,请参阅创建启用了分层命名空间的存储桶。如需了解如何装载启用了分层命名空间的存储桶,请参阅装载启用了分层命名空间的存储桶。 Google Kubernetes Engine 1.31.1-gke.2008000 或更高版本支持分层命名空间。
执行特定于目录的装载
如果您想访问存储桶中的特定目录,可以使用 only-dir
装载选项仅装载该特定目录,而不是装载整个存储桶。执行特定于目录的挂载可加快列表调用速度,并通过限制在解析文件名时要遍历的目录数量来减少列表和统计信息调用的总数,因为 LookUpInode
调用和存储桶或目录访问请求会自动为路径中的每个文件或目录生成列表和统计信息调用。
如需挂载特定目录,请使用以下方法之一:
Google Kubernetes Engine
将以下装载配置与适用于 Google Kubernetes Engine 的 Cloud Storage FUSE CSI 驱动程序搭配使用:
volumeHandle: BUCKET_NAME - only-dir:DIRECTORY_NAME
其中:
BUCKET_NAME
是要将目录装载到的存储桶的名称。DIRECTORY_NAME
是您要装载的目录的名称。
Compute Engine
运行 gcsfuse --only-dir
命令,以在 Compute Engine 虚拟机上装载特定目录:
gcsfuse --only-dir DIRECTORY_NAME BUCKET_NAME MOUNT_POINT
其中:
BUCKET_NAME
是要将目录装载到的存储桶的名称。DIRECTORY_NAME
是您要装载的目录的名称。MOUNT_POINT
是装载存储桶的本地目录。例如/path/to/mount/point
。
如需详细了解如何执行目录装载,请参阅在存储桶中装载目录。
增加元数据缓存值
为了提高重复读取的性能,您可以配置 Cloud Storage FUSE 以缓存大量元数据并绕过元数据过期,这样可以避免向 Cloud Storage 重复发送元数据请求,从而显著提高性能。
增加元数据缓存值有利于具有重复读取的工作负载,可避免重复的 Cloud Storage 调用;对于只读卷,可以设置无限 TTL。
在增加元数据缓存值之前,请考虑以下事项:
只有只读卷或仅写入新内容的卷才应设置无限存留时间 (TTL)。
元数据缓存应仅在具有大内存配置的节点上启用,以显著增加其大小,因为该缓存会缓存每个节点中指定挂载点的所有元数据,从而无需额外访问 Cloud Storage。
此部分中的配置会缓存所有访问过的元数据,并使用无限 TTL,这可能会影响一致性保证,因为任何其他客户端(例如,通过覆盖或删除文件)对同一 Cloud Storage 存储桶所做的更改都会影响一致性保证。
为验证内存消耗是否受到影响,请验证元数据缓存消耗的内存量是否在可接受范围内,该内存量可能会达到 GB 级,具体取决于已装载的存储桶中的文件数量以及正在使用的装载点数量。例如,每个文件的元数据大约占用 1.5 KiB 的内存,相对而言,一百万个文件的元数据大约占用 1.5 GiB 的内存。如需了解详情,请参阅缓存概览。
按照以下说明配置 Cloud Storage FUSE,以缓存大量元数据并绕过元数据过期:
CLI 选项
gcsfuse --metadata-cache-ttl-secs=-1 \ --stat-cache-max-size-mb=-1 \ --type-cache-max-size-mb=-1 \ BUCKET_NAME MOUNT_POINT
其中:
BUCKET_NAME
是您的存储桶的名称。MOUNT_POINT
是装载存储桶的本地目录。例如/path/to/mount/point
。
配置文件
metadata-cache: stat-cache-max-size-mb: -1 ttl-secs: -1 type-cache-max-size-mb: -1
Google Kubernetes Engine
mountOptions: - metadata-cache:ttl-secs:-1 - metadata-cache:stat-cache-max-size-mb:-1 - metadata-cache:type-cache-max-size-mb:-1
Compute Engine
gcsfuse --metadata-cache-ttl-secs=-1 \ --stat-cache-max-size-mb=-1 \ --type-cache-max-size-mb=-1 \ BUCKET_NAME MOUNT_POINT
其中:
BUCKET_NAME
是您的存储桶的名称。MOUNT_POINT
是装载存储桶的本地目录。例如/path/to/mount/point
。
预先填充元数据缓存
在运行工作负载之前,我们建议您预先填充元数据缓存,这可以显著提高性能并大幅减少对 Cloud Storage 的元数据调用次数,尤其是在使用 implicit-dirs
配置选项的情况下。适用于 GKE 的 Cloud Storage FUSE CSI 驱动程序提供了一个用于处理预先填充元数据缓存的 API,请参阅使用元数据预提取来预先填充元数据缓存。
如需预先填充元数据缓存,请使用以下方法之一:
Google Kubernetes Engine
将 gcsfuseMetadataPrefetchOnMount
CSI 卷属性标志设置为 true
:
在 Google Kubernetes Engine 1.32.1-gke.1357001 版或更高版本中,您可以使用 PersistentVolume
定义的 volumeAttributes
字段中的 gcsfuseMetadataPrefetchOnMount
配置选项为指定卷启用元数据预取。
使用 gcsfuseMetadataPrefetchOnMount
配置选项时,无需使用 initContainer
方法。
apiVersion: v1 kind: PersistentVolume metadata: name: training-bucket-pv spec: ... csi: volumeHandle: BUCKET_NAME volumeAttributes: ... gcsfuseMetadataPrefetchOnMount: "true"
其中:
BUCKET_NAME
是您的存储桶的名称。
Init 容器资源可能会因存储桶内容和分层布局而异,因此请考虑设置自定义元数据预提取边车资源以提高限制。
Linux
在 Cloud Storage FUSE 装载点上手动运行 ls -R
命令,以递归方式列出所有文件并预先填充元数据缓存:
ls -R MOUNT_POINT > /dev/null
其中:
MOUNT_POINT
:Cloud Storage FUSE 装载点的路径。
Compute Engine
在 Cloud Storage FUSE 装载点上手动运行 ls -R
命令,以递归方式列出所有文件并预先填充元数据缓存:
ls -R MOUNT_POINT > /dev/null
其中:
MOUNT_POINT
:Cloud Storage FUSE 装载点的路径。
启用文件缓存和并行下载
借助文件缓存,您可以将经常访问的文件数据存储在本地计算机上,从而加快重复读取速度并降低 Cloud Storage 费用。启用文件缓存后,系统也会自动启用并行下载。 并行下载功能利用多个工作器并行下载文件,并将文件缓存目录用作预提取缓冲区,从而将模型加载时间缩短为原来的九分之一。
如需了解如何启用和配置文件缓存及并行下载,请参阅启用和配置缓存行为。如需使用示例配置,请参阅用于启用文件缓存和并行下载的示例配置。
使用文件缓存和并行下载时需要考虑 Cloud GPU 和 Cloud TPU
文件缓存可以托管在本地 SSD、RAM、Persistent Disk 或 Google Cloud Hyperdisk 上,但需遵循以下指导原则。在所有情况下,数据或单个大文件都必须在文件缓存目录的可用容量范围内,该容量由 max-size-mb
配置控制。
Cloud GPU 注意事项
本地 SSD 非常适合用于训练数据和检查点下载。Cloud GPU 机器类型包含可用的 SSD 容量,例如包含 12 TiB SSD 的 A4 机器类型。
RAM 磁盘在加载模型权重方面可提供最佳性能,因为与系统上未使用的 RAM 量相比,模型权重的大小较小。
Persistent Disk 和 Google Cloud Hyperdisk 均可用作缓存。
Cloud TPU 注意事项
Cloud TPU 不支持本地 SSD。如果您在 Cloud TPU 上使用文件缓存而不进行修改,则使用的默认位置是启动卷,不建议这样做,因为会导致性能不佳。
我们建议您使用 RAM 磁盘,而不是启动卷,因为 RAM 磁盘的性能更好,而且不会增加成本。不过,RAM 磁盘的大小通常受到限制,最适合用于提供模型权重或检查点下载服务,具体取决于检查点的大小和可用的 RAM。 此外,我们建议使用 Persistent Disk 和 Google Cloud Hyperdisk 进行缓存。
启用文件缓存和并行下载的配置示例
默认情况下,如果为 Google Kubernetes Engine 节点启用了 ephemeral-storage-local-ssd
模式,则文件缓存会使用本地 SSD。如果没有可用的本地 SSD(例如在 Cloud TPU 机器上),文件缓存会使用 Google Kubernetes Engine 节点的启动磁盘,但不建议这样做。在这种情况下,您可以使用 RAM 磁盘作为缓存目录,但请考虑可用于文件缓存的 RAM 量与 pod 所需的 RAM 量。
CLI 选项
gcsfuse --file-cache-max-size-mb: -1 \ --file-cache-cache-file-for-range-read: true \ --file-cache-enable-parallel-downloads: true \ BUCKET_NAME
其中:
BUCKET_NAME
是您的存储桶的名称。
配置文件
file-cache: max-size-mb: -1 cache-file-for-range-read: true enable-parallel-downloads: true
Cloud GPU
mountOptions: - file-cache:max-size-mb:-1 - file-cache:cache-file-for-range-read:true - file-cache:enable-parallel-downloads:true # RAM disk file cache if LSSD not available. Uncomment to use # volumes: # - name: gke-gcsfuse-cache # emptyDir: # medium: Memory
Cloud TPU
mountOptions: - file-cache:max-size-mb:-1 - file-cache:cache-file-for-range-read:true - file-cache:enable-parallel-downloads:true volumes: - name: gke-gcsfuse-cache emptyDir: medium: Memory
Compute Engine
gcsfuse --file-cache-max-size-mb: -1 \ --file-cache-cache-file-for-range-read: true \ --file-cache-enable-parallel-downloads: true \ BUCKET_NAME MOUNT_POINT
其中:
BUCKET_NAME
是您的存储桶的名称。MOUNT_POINT
是装载存储桶的本地目录。例如/path/to/mount/point
。
停用负统计信息缓存条目
默认情况下,Cloud Storage FUSE 会缓存负统计信息条目(即不存在的文件的条目),TTL 为 5 秒。在频繁创建或删除文件的工作负载(例如分布式检查点)中,这些缓存的条目很快就会过时,从而导致性能问题。为避免这种情况,我们建议您使用 negative-ttl-secs
配置选项为训练、服务和检查点工作负载停用负统计信息缓存。
按照以下说明停用负统计信息缓存:
CLI 选项
gcsfuse --metadata-cache-negative-ttl-secs: 0 \ BUCKET_NAME
其中:
BUCKET_NAME
是您的存储桶的名称。
配置文件
metadata-cache: negative-ttl-secs: 0
Google Kubernetes Engine
mountOptions: - metadata-cache:negative-ttl-secs:0
Compute Engine
gcsfuse --metadata-cache-negative-ttl-secs: 0 \ BUCKET_NAME MOUNT_POINT
其中:
BUCKET_NAME
是您的存储桶的名称。MOUNT_POINT
是装载存储桶的本地目录。例如/path/to/mount/point
。
启用流式写入
流式写入会在写入数据时将其直接上传到 Cloud Storage,从而减少延迟和磁盘空间用量。这对于大型顺序写入(例如检查点)特别有用。在 Cloud Storage FUSE 3.0 及更高版本中,流式写入默认处于启用状态。
如果未默认启用流式写入,请按照以下说明启用。启用流式写入需要 Cloud Storage FUSE 版本 3.0,该版本可在 Google Kubernetes Engine 版本 1.32.1-gke.1729000 或更高版本中使用。
CLI 选项
gcsfuse --enable-streaming-writes: true \ BUCKET_NAME
其中:
BUCKET_NAME
是您的存储桶的名称。
配置文件
write: enable-streaming-writes: true
Google Kubernetes Engine
mountOptions: - write:enable-streaming-writes:true
Compute Engine
gcsfuse --enable-streaming-writes: true \ BUCKET_NAME MOUNT_POINT
其中:
BUCKET_NAME
是您的存储桶的名称。MOUNT_POINT
是装载存储桶的本地目录。例如/path/to/mount/point
。
增加内核预读大小
对于主要涉及顺序读取大文件的工作负载(例如传送和检查点恢复),增加预读大小可以显著提高性能。您可以使用本地计算机上的 read_ahead_kb
Linux 内核参数来实现这点。我们建议您将 read_ahead_kb
内核参数增加到 1 MB,而不是使用大多数 Linux 发行版上设置的默认值 128 KB。对于 Compute Engine 实例,必须具有 sudo
或 root
权限才能成功增加内核参数。
如需将特定 Cloud Storage FUSE 装载目录的 read_ahead_kb
内核参数增至 1 MB,请按照以下说明操作。您必须先将存储桶装载到 Cloud Storage FUSE,然后才能运行该命令,否则内核参数不会增加。
Google Kubernetes Engine
mountOptions: - read_ahead_kb=1024
Compute Engine
export MOUNT_POINT=/path/to/mount/point echo 1024 | sudo tee /sys/class/bdi/0:$(stat -c "%d" $MOUNT_POINT)/read_ahead_kb
其中:
MOUNT_POINT
:Cloud Storage FUSE 装载点的路径。
停用 Security Token Service 以避免冗余检查
Google Kubernetes Engine 的 Cloud Storage FUSE CSI 驱动程序具有访问权限检查功能,可确保 pod 在以下情况下能够恢复:用户错误配置了存储桶与 GKE 服务账号之间的工作负载身份绑定,这可能会大规模达到 Security Token Service API 的默认配额。您可以通过设置永久性卷 CSI 驱动程序的 skipCSIBucketAccessCheck
卷属性来停用此功能。我们建议您确保 GKE 服务账号对目标 Cloud Storage 存储桶具有适当的访问权限,以避免 Pod 出现装载失败的情况。
此外,如果 Google Kubernetes Engine 集群包含 6,000 多个节点,则必须将 Security Token Service 配额增加到超出默认值 6000
,否则在大型部署中可能会导致 429
错误。必须通过“配额和限制”页面增加 Security Token Service 配额。我们建议您将配额保持为装载数量,例如,如果集群中有 10,000 个装载,则应将配额增加到 10000
。
如需设置 skipCSIBucketAccessCheck
卷属性,请参阅以下示例配置:
volumeAttributes: - skipCSIBucketAccessCheck: "true"
其他性能注意事项
除了上述主要优化措施外,还有几个其他因素会显著影响 Cloud Storage FUSE 的整体性能。以下部分介绍了使用 Cloud Storage FUSE 时建议考虑的其他性能注意事项。
提高非 HNS 存储桶的重命名限制
检查点工作负载应始终使用启用了分层命名空间的存储桶来完成,因为这样可以实现原子性、更快的重命名以及更高的读写 QPS。不过,如果您愿意承担目录重命名操作并非原子操作且耗时更长的风险,则可以使用 rename-dir-limit
配置选项(如果您使用不含分层命名空间的存储桶执行检查点操作),以指定在任何给定时间参与目录重命名操作的文件或操作数量的上限。
建议将 rename-dir-limit
配置选项设置为较高的值,以防止检查点设置失败。由于 Cloud Storage FUSE 使用平面命名空间,并且对象不可变,因此目录重命名操作涉及重命名和删除目录中的所有单个文件。您可以通过设置 rename-dir-limit
配置选项来控制重命名操作影响的文件数量。
按照以下说明设置 rename-dir-limit
配置选项:
CLI 选项
gcsfuse --rename-dir-limit: 200000 \ BUCKET_NAME
其中:
BUCKET_NAME
是您的存储桶的名称。
配置文件
file-system: rename-dir-limit: 200000
Google Kubernetes Engine
mountOptions: - rename-dir-limit=200000
Compute Engine
gcsfuse --rename-dir-limit: 200000 \ BUCKET_NAME MOUNT_POINT
其中:
BUCKET_NAME
是您的存储桶的名称。MOUNT_POINT
是装载存储桶的本地目录。例如/path/to/mount/point
。
内核列表缓存
列表缓存是目录和文件列表或 ls
响应的缓存,可提高列表操作的速度。与由 Cloud Storage FUSE 管理的状态和类型缓存不同,列表缓存保留在内核的页面缓存中,由内核根据内存可用性进行控制。
启用内核列表缓存对以下使用场景最为有利:
需要重复列出目录的工作负载:此配置对于需要频繁列出完整目录的工作负载(例如 AI/机器学习训练运行)尤其有用。这有助于提升服务和训练工作负载的性能。
只读装载:建议使用只读装载进行列表缓存,以避免出现一致性问题。
启用内核列表缓存时应谨慎操作,并且只有在文件系统确实为只读且作业执行期间预计不会发生目录内容更改时才应使用。这是因为,如果设置了此标志,本地应用永远不会看到更新,尤其是在 TTL 设置为 -1
的情况下。
例如,客户端 1 列出了 directoryA
,这会导致 directoryA
成为内核列表缓存中的常驻项。客户端 2 在 Cloud Storage 存储桶中的 directoryA
下创建 fileB
。客户端 1 会持续检查 directoryA
中的 fileB
,这实际上是在检查内核列表缓存条目,并且永远不会通过网络进行检查。客户端 1 看不到目录中有新文件,因为文件列表始终从本地内核列表缓存中提供。然后,客户端 1 超时,程序中断。
使用以下指令启用列表缓存:
CLI 选项
gcsfuse --kernel-list-cache-ttl-secs: -1 \ BUCKET_NAME
其中:
BUCKET_NAME
是您的存储桶的名称。
配置文件
file-system: kernel-list-cache-ttl-secs: -1
Google Kubernetes Engine
mountOptions: - file-system:kernel-list-cache-ttl-secs:-1
Compute Engine
gcsfuse --kernel-list-cache-ttl-secs: -1 \ BUCKET_NAME MOUNT_POINT
其中:
BUCKET_NAME
是您的存储桶的名称。MOUNT_POINT
是装载存储桶的本地目录。例如/path/to/mount/point
。
使用 file-system:kernel-list-cache-ttl-secs
装载选项时,这些值具有以下含义:
一个正值,表示存留时间 (TTL)(以秒为单位),以将目录列表响应保留在内核的页面缓存中。
值为
-1
可绕过条目到期时间,并在缓存可用时返回列表响应。
将 JAX 持久编译 (JIT) 缓存与 Cloud Storage FUSE 搭配使用
JAX 支持即时 (JIT) 缓存,这是一种可选的持久性编译缓存,用于存储已编译的函数制品。使用此缓存后,您可以避免冗余的编译步骤,从而显著加快后续脚本执行速度。
如需启用 JIT 缓存,您必须满足以下要求:
使用最新版本的 JAX:使用 JAX 版本 0.5.1 或更高版本,以获取最新的缓存功能和优化。
最大限度地提高缓存容量:为防止因缓存逐出而导致性能下降,请考虑设置无限的缓存大小,尤其是在您想要替换默认设置的情况下。您可以通过设置以下环境变量来实现此目的:
export JAX_COMPILATION_CACHE_MAX_SIZE=-1
确保检查点 pod YAML:使用装载点的检查点配置(用于 JAX JIT 缓存)。
后续步骤
使用示例 Google Kubernetes Engine YAML 文件来配置调优最佳实践。