毫末智行是一家致力于自动驾驶,提供智能物流解决方案的人工智能技术公司。数据智能是毫末智行的核心能力,乘用车自动驾驶系统及解决方案、低速无人车生态系统及解决方案、自动驾驶相关产品研发与定制服务三大垂类产品为数据智能服务,同时,数据智能也反哺三大垂类产品。
传统机器学习训练性能瓶颈
随着机器学习在自动驾驶业务场景中得到广泛使用,机器学习平台扮演了非常核心的角色。该平台采用了存储与计算分离的架构,使得计算资源得以与存储资源解耦, 从而实现了灵活的资源配比以及便捷的存储扩展,并且降低了存储资金和运维成本。
然而,这种架构也带来了一些挑战,其中比较关键的问题体现在数据访问性能和稳定性方面:
- 计算存储分离架构导致数据访问高延时,导致训练慢:业务团队使用的机器学习任务在训练过程中要实时频繁访问 OSS 上的数据,在 OSS 带宽受限或者压力较大时, 访问 OSS 上数据速度比访问本地文件速度要慢很多;
- Kubernetes 调度器数据缓存无感知,同一数据源多次运行访问依旧慢: 在现实应用中深度学习任务运行会不断 重复访问同一数据,包括相同模型不同超参的任务、微调模型相同输入的任务、以及 AutoML 任务等。这种深度学习任务的重复数据访问就产生了可以复用的数据缓存。然而,由于原生 Kubernetes 调度器无法感知缓存,导致应用调度的结果不佳,缓存无法重用,性能难以提升;
- OSS 成为数据并发访问的瓶颈点,稳定性挑战大: 毫末机器学习平台上的大量机器学习任务在同时训练时都会并发访问后端 OSS 存储。这种并发机器学习训练造成的 IO 压力比较大, OSS 服务成为了性能单点,一旦 OSS 带宽出现瓶颈则会影响所有机器学习任务;
- 训练文件分散,元数据压力大: 机器学习任务的训练数据文件通常会分散在不同路径下,读取文件需要耗费大量的时间在 list 操作上。对象存储的 list 操作性能较差, 因此在进行大规模 list 时对 OSS 元数据压力很大,经常出现超时或者 list 失败的情况。
在现实应用中,通过对于毫末机器学习平台的监控分析,我们发现 IO 性能问题会导致 GPU 等昂贵计算资源不能被充分利用。机器学习自身训练的特点导致了数据文件访问较分散,元数据压力较大。如果能够精细化地缓存元数据和文件数据,那么一方面可以提高缓存效率和磁盘利用率,另一方面也可以解决文件查找操作带来的元数据损耗。
开源让智能驾驶加速拥抱云原生 AI
为了能更好地满足大规模机器学习模型训练的高效性需求,模型训练过程中需要对数据访问取得更好的数据本地化效果。因此,我们希望达到以下目标:
- 计算能够充分利用本地化数据访问:这样就不需通过网络反复读取,从而加速机器学习模型的训练速度,并提升集群的 GPU 使用率。
- 降低 OSS 负载压力:通过应用对于部分数据的本地读取,减小数据访问延时和降低对底层 OSS 的带宽压力。
- 充分发挥热点数据集的缓存节点优势:在对用户无感知的前提下,智能地将任务调度到数据缓存节点上,从而使得常用模型训练程序越来越快。
- 自定义文件列表形式缓存指定文件:只缓存训练需要的文件,极大提高缓存使用率和磁盘利用率。
- 元数据缓存和数据缓存分离:可单独对文件进行元数据缓存,缓存策略定制化。
- 通过 POSIX 接口读取数据:这样无需在模型开发和训练阶段使用不同的数据访问接口,降低开发机器学习模型程序的成本。
为了达到上述目标,我们迫切希望找到 Kubernetes 上具有分布式缓存加速能力的系统平台。我们发现 CNCF Sandbox 项目 Fluid 正好可以满足我们的诉求。于是,我们设计了基于 Fluid 的新架构方案,经过验证比较,我们选择 JindoRuntime 作为加速运行时。
技术方案
Fluid
Fluid 是一个运行在 Kubernetes 上可扩展的分布式数据编排和加速系统,它通过数据的编排和 使用数据的应用调度,解决云原生编排框架运行此类应用面临数据访问延时高、多数据源联合分析难、应用使用数据过程复杂等痛点。
JindoRuntime
JindoRuntime 是 Fluid 一种分布式缓存 Runtime 的实现,基于 JindoFS 分布式缓存加速引擎。JindoFS 是阿里云开源大数据-数据湖存储团队自研大数据存储优化引擎,完全兼容 Hadoop 文件系统接口,给客户带来更加灵活、高效的计算存储方案。JindoRuntime 使用 JindoFS 的 Cache 模式进行远端文件的访问和缓存,支持 OSS、HDFS、标准 S3 协议等多种存储产品的访问和缓存加速。在 Fluid 上使用和部署 JindoRuntime 流程简单、兼容原生 K8s 环境、可以开箱即用。深度结合对象存储特性,使用 Navite 框架优化性能,并支持免密、checksum 校验等云上数据安全功能。
之所于选型基于 JindoRuntime 的 Fluid,主要是基于以下考虑:
- Fluid 可以将数据集编排在 Kubernetes 集群中,实现数据和计算的同置,并且提供基于 Persistent Volume Claim 接口,实现 Kubernetes 上应用 的无缝对接。同时 JindoRuntime 提供对 OSS 上数据的访问和缓存加速能力,并且可以利用 FUSE 的 POSIX 文件系统接口实现可以像本地磁盘一样轻松使用 OSS 上的海量文件,pytorch 等深度学习训练工具可利用 POSIX 文件接口读取训练数据。
- 提供元数据和数据分布式缓存,可单独进行元数据缓存预热。
- 提供元数据缓存预热,避免训练文件在 OSS 上大量元数据操作、提供数据预热机制,避免在训练时刻拉取数据造成的数据访问竞争
- 提供文件列表形式的数据定制化预热,精细化预热数据。
- 通过 Fluid 的数据感知调度能力,用户无需知道缓存节点信息就可以将任务放置到有缓存数据的节点,实现数据访问性能的优势最大化。
落地实践
- 选择合适的缓存节点: 使用 JindoRuntime 可以获得更好的数据本地性能,在实际生产中我们发现不是所有节点都来做缓存性能就比较好。原因是有些 节点的磁盘和网络 IO 性能不是很好,这个时候需要我们能够把缓存节点尽量选择到一些大容量磁盘和网络较好的节点上。Fluid 支持 dataset 的可调度性,换言 之,就是缓存节点的可调度性,我们通过指定 dataset 的 nodeAffinity 来进行数据集缓存节点的调度,从而保证缓存节点可高效的提供缓存服务。
- 配置缓存容量与路径: 通过 dataset 的 Mounts 和 JindoRuntime 的 tieredstore 可以设定数据的挂载目录。同时,为避免数据量过多而导致 缓存量过于庞大,可手动配置 JindoRuntime 的 tieredstore 来约束缓存的最大容量与水位线(超过水位线的数据会被自动丢弃),tieredstore 也包含对缓存 存放路径的设定与存储层(SSD/MEM/HDD)的设定,以满足各种场景的需要。对于多节点的场景,使用 dataset 的 replacement 可以支持在同一集群上部署多个 dataset。
- 设定缓存安全策略: 在 Fluid 中创建 Dataset 时,有时候我们需要在 mounts 中配置一些敏感信息,如 oss 账号的 accessKeyId、accessKeySecret 。 为了保证安全,Fluid 提供使用 Secret 来配置这些敏感信息的能力。通过创建 Secret,dataset 以 EncryptOptions 字段指定 Secret 的 name,实现对敏感信息的绑定。
- 数据预加载: 对于已经创建完成的 dataset 和 jindoruntime,第一次访问挂载的数据会经历一次下载数据目录下全部文件的过程,这就产生了一个问题: 若数据所在的目录存在无需使用的其他数据,会造成无意义的空间资源与网络资源浪费。为避免这种问题,Fluid 既支持对数据的预加载,同时也支持元数据缓存。通 过创建 dataload 读取所要预加载数据路径信息,可以动态将数据注入。dataload 支持缓存元数据与屏蔽非预加载数据的访问,这样就大大降低的数据访问效率。
带来性能的显著提升
我们使用了不同的模型,推理和训练相同的数据,分别以使用 JindoRuntime 和不使用 JindoRuntime 的方式推理和训练,对比训练时长,发现性能带来了显示提升:
模型在云端推理1万帧图片的测试结果
另一稍的模型在云端推理1万帧图片的测试结果
模型使用 4 卡在云端训练1万帧图片帧耗时测试结果
集成了 Fluid+JindoRuntime 后,显著提升了云端训练和推理的效率,尤其是一些小模型,在云端做训练和推理 JindoRuntime 可以有效解决 IO 瓶颈问题,训练速度最高可提升约 300% 。同时也大幅度提升云端 GPU 使用效率,加速了在云端数据驱动的迭代效率。
共建开源生态,让更多行业更“聪明”
毫末机器学习训练场景对于数据读取有较高的性能要求,且对于元数据和数据缓存的精细化控制要求较高, 通过 Fluid + JindoRuntime 的缓存能力可以灵活地缓存 OSS 训练文件进行元数据和数据,提供高效的元数据和数据访问性能。 基于这种方案,我们可以实现精细化控制缓存的内容,提高生产资源利用率,不仅有效缓解了 OSS 带宽的压力,也大大提高了训练效率。
当前 Fluid + JindoRuntime 能够满足生产环境的基本需要,对 OSS 的加速效果也比较明显,提供的精细化缓存策略更加高效。 我们期望能够把弹性的数据加速作为毫末机器学习平台的差异化竞争能力,提升整体训练任务速度和计算资源的利用率。在未来的工作中,我们也希望也帮助社区不断演进,帮助到更多的开发者。具体来说,后面在平台中计划增加的功能包括:
- 支持定时任务支持动态扩缩容
- 提供性能监控控制台
- 支持规模化 K8s 集群中多数据集的全生命周期管理
- 支持对缓存数据和缓存元数据的动态删减
作者
李范:毫末智行服务端开发工程师,负责 AI 自动训练平台的研发与算法优化。
陈铁文:毫末智行服务端开发工程师,负责 AI 自动训练平台的上层研发。
关于毫末智行
经近 10 年的积累与全栈自研,以及 90% 以上的研发投入,毫末智行在乘用车、低速无人车、智能硬件三个方面不断积累相关数据,目前已孵化出小魔盒、小魔驼、小魔盘等 10 余款成熟产品。毫末智行的快速发展也体现着更高级别的智能驾驶将在更广泛的场景中发挥作用,自动驾驶的商业应用正在驶入快车道。
致谢
感谢阿里云 JindoFS 团队的辰山、扬礼和容器团队的车漾在整个方案设计和优化过程中的巨大帮助,对生产过程中的需求给予定制化的支持,对遇到的各种问题进行快速的帮助和解决。
相关链接
[1] Fluid: https://github.com/fluid-cloudnative/fluid
[2] JindoFS: https://github.com/aliyun/alibabacloud-jindodata
更多 Fluid 和 JindoFS 相关介绍请参考以上链接。