如何借助分布式存储 JuiceFS 加速 AI 模型训练

这篇具有很好参考价值的文章主要介绍了如何借助分布式存储 JuiceFS 加速 AI 模型训练。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

传统的机器学习模型,数据集比较小,模型的算法也比较简单,使用单机存储,或者本地硬盘就足够了,像 JuiceFS 这样的分布式存储并不是必需品。

随着近几年深度学习的蓬勃发展,越来越多的团队开始遇到了单机存储的瓶颈,分布式存储在 AI 领域的重要性不断凸显。AI 团队通常会面临以下几种问题:

数据集太大

随着数据量和模型规模的增加,单机存储往往无法满足需求。为解决这些问题,就需要使用分布式存储。

历史数据集需要进行全量归档

在某些应用场景每天都会产生大量新的数据集,这些数据集在一段时间后将变为历史数据,需要进行归档。由于这些数据的生成成本较高,因此不能轻易删除,尤其是在自动驾驶领域,如路测车采集的雷达和摄像头数据,这些数据对公司来说是极为宝贵的资产。若要整理这些数据,传统的单机存储显然不足以满足需求,因此需要考虑使用分布式存储。

小文件和非结构化数据太多

针对传统的分布式文件系统,管理大量小文件会带来元数据存储的负担,对于视觉类模型,影响更加明显。解决这一问题的方法是使用对小文件存储友好的分布式存储系统,这样可以保证上层训练任务的高效率,同时也能够方便地管理大量的小文件。

训练框架需要 POSIX 接口

最初算法科学家在做模型调研时,都是基于本地的资源来做研发和数据的访问,但当需要在分布式存储上进行更大规模的训练时,原本的代码一般不会做太多的调整。所以这就要求分布式存储需要支持 POSIX 接口,最大程度上兼容本地开发阶段的代码。

公共数据集需要不同团队共享,也可能需要数据隔离

在某些领域,如计算机视觉,有一些权威的公共数据集,这些数据集需要在公司内部不同的团队间共享。为了方便团队之间的使用,通常会将这些数据整合并打包存储到一个共享存储中,避免不必要的数据复制和冗余。

云上训练的数据 I/O 效率不高

在云上进行模型训练通常是使用对象存储作为底层存储的存算分离架构,由于对象存储的读写性能较差,在训练上会有很大的瓶颈。

本文将会介绍在模型训练中如何使用 JuiceFS,以及优化训练效率的实践。

1.JuiceFS 在模型训练场景中的架构

上图是架构图,分为三个部分:

第一部分:元数据引擎,根据个人选择,可以使用任何数据库,例如 Redis、MySQL 等等,作为元数据引擎。

第二部分:底层数据存储,在云上或私有云中,使用对象存储服务来对接 JuiceFS。

第三部分:JuiceFS 客户端,用户在使用时需要在每个 GPU 和计算节点上挂载 JuiceFS,这样就可以像访问本地硬盘一样访问 JuiceFS 的文件系统。

底层存储依赖于对象存储中的原始数据,同时每个计算节点上还有一些本地缓存,包括元数据和数据缓存。JuiceFS 的设计中,每个计算节点的本地可以有多级缓存。第一级是基于内存的缓存,第二级是基于本地磁盘的缓存,只有在本地缓存没有命中时,才会访问对象存储。

如果进行单机模型训练,在首轮训练时,训练集或数据集通常不会命中缓存。但是从第二轮开始,在缓存资源充足的情况下,几乎不需要访问对象存储,达到加速数据 I/O 的效果。

JuiceFS 读写缓存流程

我们之前进行了一项评测,比较了在访问对象存储时,使用缓存和不使用缓存这两种方式对于训练效率的影响。评测结果表明,这两种方式的性能差别非常大。(点击 此处,了解评测结果)

上图展示了 JuiceFS 缓存读写的流程。最上面是应用程序,它相当于是最初发起读请求的起点应用或训练任务。

当应用程序发起读请求后,请求会先进入左侧的内核空间,内核会查看内核页缓存中是否有请求的数据。如果内核页缓存中没有数据,请求会回到用户空间的 JuiceFS 进程。在用户空间,JuiceFS 进程会处理所有的读写请求。

JuiceFS 默认会在内存中维护一个读缓冲区,当请求未能从缓冲区中获取数据时,JuiceFS 会进入块缓存索引,即基于本地磁盘的缓存目录。JuiceFS 默认将文件切割成 4MB 的块并存储,因此缓存的粒度也是 4MB。

举个例子,当访问一个文件的一部分数据时,JuiceFS 只会缓存该部分数据对应的 4MB 块到本地缓存目录中,而不会缓存整个文件。这是 JuiceFS 与其他文件系统或缓存系统的显著差异之一。

Block cache index 用于快速定位本地缓存目录中的文件块。如果找到了,JuiceFS 进程会自动读取本地盘,然后进入内核态,读取完成后返回给 JuiceFS 进程,最后返回给应用程序。

当本地盘数据读取完成后,数据还会进入内核页缓存。这是因为如果没有使用 direct I/O,Linux 系统默认会将数据存储在内核页缓存中。这些内核页缓存都用于加速缓存访问,如果第一个请求直接命中并返回,那么效率是最高的,并且请求不会通过 FUSE 层进入用户态进程。如果没有命中,则会通过 index 查找,如果在节点目录中没有找到 block,则会通过网络请求到达对象存储,然后将数据读回来并原路返回给应用程序。

从对象存储上下载数据时,JuiceFS 会有一个后台异步线程,把读回来的 block 同时写到本地缓存盘里,确保下一次访问同样的 block 时,能直接从本地缓存命中,而不需要再次从对象存储上获取。以上就是 JuiceFS 建立读缓存的流程。

上图有一部分的模块叫 Chunk Cache,chunk 是 JuiceFS 中的一个逻辑概念,每个文件会按照 64MB 大小分为多个 chunk,来提升大文件的读取性能。这部分信息会被缓存到 JuiceFS 进程的内存里,来加速元数据访问的效率。

与数据缓存不同,元数据缓存时间较短,并且为确保强一致性,open 操作默认不缓存。考虑到元数据流量很小,所以对整体的 I/O 性能影响比较小,但是在大量小文件的场景,如果需要频繁访问小文件,元数据的开销也会占到一定的比重。

2.为什么训练太慢以及如何排查?

当使用 JuiceFS 进行训练时,性能是最重要的考虑因素,它直接影响到模型训练的速度。以下是可能影响 JuiceFS 效率的几个方面:

元数据引擎

在处理小文件时,选择不同的元数据引擎(如 Redis、TiKV、MySQL)的性能差别很大。JuiceFS 官网提供了一份对比它们作为元数据引擎的性能文档,平均来说 Redis 会比其他数据库快 3~5 倍。如果发现元数据请求特别慢,建议尝试使用一些性能更好的数据库作为 JuiceFS 的元数据引擎。

对象存储

主要影响数据存储访问的性能和吞吐量。如果在云上使用,通常使用公有云提供的对象存储服务,其性能相对固定。如果使用自建的对象存储,例如使用开源的 Ceph 或 MinIO 组件,可以对组件进行调优以达到更好的性能和吞吐量。

本地磁盘

缓存目录存储的位置对整个读取性能影响很大。在缓存命中率高的情况下,缓存磁盘的 I/O 效率会直接影响整体 I/O 效率。因此需要注意存储类型、存储介质以及磁盘容量等因素,数据集的大小也会对训练效率产生影响。

网络带宽

在第一轮训练完成后,如果数据集不足以在本地完全缓存,网络带宽或网络资源的消耗会影响整体数据访问效率。在云上,不同机型的网卡带宽也有所不同,这也会对数据的访问速度和效率产生影响。

内存

内存的大小会直接影响内核页缓存的大小。当内存足够大时,剩余的空闲内存可以用作 JuiceFS 数据的缓存,进一步加快数据的访问速度。但是,当剩余的空闲内存较少时,数据访问需要通过本地磁盘获取,这会导致访问开销变大。另外,内核态和用户态之间的切换会对性能造成影响,比如系统调用的上下文切换开销等。

如何排查

JuiceFS 提供了许多工具和命令来帮助用户更好地进行性能调优和诊断。在去年的 Office Hours 中,已经对如何在 JuiceFS 中进行性能调优和诊断进行了全面介绍。如果感兴趣,可以在 B 站上观看视频回放。以下是其中几个方法的简要介绍:

工具1 :juicefs profile 命令

它可以通过分析访问日志来帮助用户更好地优化性能。每个文件系统挂载之后都会有访问日志,但访问日志并不会实时保存,只有在查看访问日志时才会显示出来。相比直接查看原始的访问日志,juicefs profile 命令会进行信息的聚合和类似滑动窗口的数据统计,并按照响应时间从高到低排序,帮助用户优先关注响应时间较慢的请求,进一步分析请求与元数据引擎或对象存储的关系。

工具2:juicefs stats 命令

它从更宏观的角度收集监控数据,并实时展示出来。它可以监控当前挂载点的 CPU 占用、内存占用、内存中的缓冲区占用、FUSE 读写请求、元数据请求以及对象存储的延迟情况等。这些细致的监控指标可以方便用户查看和分析当前模型训练的瓶颈或性能问题出现的可能环节。

JuiceFS 还提供了更底层的信息分析工具,包括 CPU profile 和 heap profile。CPU profile 可以分析 JuiceFS 进程执行速度的瓶颈所在,适用于熟悉源代码的用户。而 heap profile 则主要用于分析内存占用情况,尤其是当 JuiceFS 进程占用大量内存时,需要使用 heap profile 来确定具体哪些函数或数据结构占用了较多内存。

3.一些常见的优化策略

元数据缓存优化

元数据缓存的优化方案主要分为两类:

1)调整内核元数据缓存的超时时间

可以使用 --attr-cache--entry-cache--dir-entry-cache 参数,这三个参数分别对应不同类型的元数据:attr 表示文件属性(如大小、修改时间、访问时间等),entry 是 Linux 中的概念,表示文件和相关属性,dir-entry 表示目录和其中包含的文件。

这些参数分别控制着元数据缓存的超时时间。为了保证数据访问的一致性,这些参数的默认值只有一秒钟,但在模型训练的场景中,原始数据通常不会被修改,因此可以将这些参数的超时时间设置得更长一些,比如几天到一周等。但需要注意的是,元数据缓存是无法主动失效的,只能等待超时时间到期。

2)优化 JuiceFS 客户端的用户态元数据缓存

默认情况下,在打开文件时会强制请求元数据引擎获取最新的文件属性,以保证强一致性。但由于模型训练的数据通常不会被修改,因此可以打开 --open-cache 参数,并设置一个超时时间,以避免每次打开同一个文件都重复访问元数据引擎。另外可以通过 --open-cache-limit 参数控制缓存的最大文件数,默认值是 10000,即最多缓存最近打开的 10000 个文件的元数据在内存中,可以根据数据集的文件个数进行适当调整。

数据缓存

JuiceFS 的数据缓存分为内核页缓存和本地数据缓存两种,其中内核页缓存无法进行参数调优。因此,在计算节点上应该尽量保留足够的空闲内存,以便 JuiceFS 能够充分利用。如果计算节点上的资源紧张, JuiceFS 就不会将数据缓存到内核中。

而本地数据缓存相对来说用户更加可控,可以根据具体场景调优缓存参数。首先,可以调整缓存的大小( --cache-size),默认值为 100G,对于大部分场景都足够了。但是对于占用空间特别大的数据集,需要适当调整缓存大小,否则 100G 的缓存空间可能很快被写满,导致 JuiceFS 无法缓存更多数据。配合 --cache-size 参数一起使用的另一个参数是 --free-space-ratio,这个参数用于控制缓存盘的空间空闲比例,默认值是 0.1,即最多使用 90% 的磁盘空间缓存数据。

JuiceFS还支持同时使用多个缓存盘,推荐尽量使用所有可用的盘。数据会通过轮询的方式均匀分布到多个盘中,从而实现负载均衡,同时最大化利用多块盘的存储优势。

缓存预热

为了提高训练效率,可以通过预热缓存来加速训练任务。JuiceFS 支持预热客户端中的元数据缓存和本地数据缓存,通过使用 juicefs warmup 命令可以将缓存提前预热到缓存盘,从而在训练任务开始时直接命中缓存,提高效率。

增大缓冲区大小

缓冲区的大小也会影响读取性能。默认情况下,缓冲区大小为 300MB,但在高吞吐的训练场景下,这可能不够用。可以根据训练节点的内存资源情况来调整缓冲区大小,一般来说,缓冲区越大读取性能越好,但也不要设置过大的值(特别是在限制了最大内存的容器环境中)。需要结合实际负载情况进行调优,找到一个相对合理的缓冲区大小。可以参考前面介绍的 juicefs stats 命令实时观测缓冲区的使用量。

如有帮助的话欢迎关注我们项目 Juicedata/JuiceFS 哟! (0ᴗ0✿)文章来源地址https://www.toymoban.com/news/detail-426022.html

到了这里,关于如何借助分布式存储 JuiceFS 加速 AI 模型训练的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据存储和分布式计算的实际应用:如何使用Spark和Flink进行数据处理和分析

    作为一名人工智能专家,程序员和软件架构师,我经常涉及到数据处理和分析。在当前大数据和云计算的时代,分布式计算已经成为了一个重要的技术方向。Spark和Flink是当前比较流行的分布式计算框架,它们提供了强大的分布式计算和数据分析功能,为数据处理和分析提供了

    2024年02月16日
    浏览(49)
  • 【分布式】分布式存储架构

    说到分布式存储,我们先来看一下传统的存储是怎么个样子。 传统的存储也称为集中式存储, 从概念上可以看出来是具有集中性的,也就是整个存储是集中在一个系统中的,但集中式存储并不是一个单独的设备,是集中在一套系统当中的多个设备,比如下图中的 EMC 存储就需

    2024年02月10日
    浏览(43)
  • 【分布式技术】分布式存储ceph之RBD块存储部署

    目录 创建 Ceph 块存储系统 RBD 接口 服务端操作 1、创建一个名为 rbd-demo 的专门用于 RBD 的存储池 2、将存储池转换为 RBD 模式 3、初始化存储池 4、创建镜像 5、在管理节点创建并授权一个用户可访问指定的 RBD 存储池 6、修改RBD镜像特性,CentOS7默认情况下只支持layering和stripin

    2024年01月18日
    浏览(68)
  • 分布式键值存储是什么?(分布式键值存储大值)

    分布式键值存储是一种分布式数据存储系统,它将数据存储为键值对的形式,并将这些键值对分散在多个节点上。每个节点都可以独立地处理一部分数据,从而实现高可用性和可扩展性。分布式键值存储通常具有以下特点: 简单:数据以键值对的形式存储,操作简单,易于使

    2024年02月03日
    浏览(35)
  • 云存储、云计算与分布式存储、分布式计算是一回事吗?

    随着互联网的蓬勃兴起,大数据、人工智能、物联网、云计算与云存储等这些专业词汇在大众视野内出现的频率越来越高,再加上近几年分布式技术异军突起,更使得分布式存储、分布式计算等成为热词。然而,很多人对这些名词都一知半解,所以本文将主要和大家聊一聊,

    2024年01月25日
    浏览(54)
  • 【分布式技术】分布式存储ceph之RGW接口

    目录 1、对象存储概念  2、创建 RGW 接口 //在管理节点创建一个 RGW 守护进程 #创建成功后默认情况下会自动创建一系列用于 RGW 的存储池  #默认情况下 RGW 监听 7480 号端口  //开启 http+https ,更改监听端口 #更改监听端口 ​          //创建 RadosGW 账户 客户端测试 OSD 故障模拟

    2024年01月19日
    浏览(52)
  • 分布式系统架构设计之分布式数据存储的扩展方式、主从复制以及分布式一致性

    在分布式系统中,数据存储的扩展是为了适应业务的增长和提高系统的性能。分为水平扩展和垂直扩展两种方式,这两种方式在架构设计和应用场景上有着不同的优势和局限性。 水平扩展是通过增加节点或服务器的数量来扩大整个系统的容量和性能。在数据存储领域,水平扩

    2024年02月03日
    浏览(60)
  • 分布式数据(文件)存储

    在分布式存储里面,比较常见的有kafka,Hbase,HDFS,fastDFS等,这里面涉及到文件的分布式存储以及数据的分布式存储。分布式存储的背景:就是将数据文件分散的存储到分布式集群的每一个节点,提升了存储的容量(大数据化);同时尽量凸显分布式的检索能力。分布式存储的原

    2024年02月07日
    浏览(42)
  • ceph分布式存储

    Ceph是当前非常流行的开源分布式存储系统,具有高扩展性、高性能、高可靠性 等优点,同时提供块存储服务(rbd)、对象存储服务(rgw)以及文件系统存储服务(cephfs),Ceph在存储的时候充分利用存储节点的计算能力,在存储每一个数据时 都会通过计算得出该数据的位置,尽量的分

    2023年04月08日
    浏览(41)
  • etcd分布式存储

    etcd分布式存储 etcd简介 etcd下载安装 etcd常用命令 etcd配置参数 etcd集群 golang操作etcd

    2024年02月09日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包