如文章《幻方力量 | 高速文件系列 3FS》中所介绍的,幻方AI设计了一套非常适合深度学习训练的样本读取文件系统,3FS,其采用 Direct IO 和 RDMA Read 的读取方式,让模型训练在样本读取部分只用极小的 CPU 和内存开销,就可以获得超高的读取带宽,从而无需再训练过程中等待加载数据,更充分地利用起 GPU 的计算性能。
我们知道,文件系统一般分为客户端与服务端。在 3FS 文件系统中,客户端部署在计算节点侧,通过网络访问部署在存储节点侧的 3FS 服务端。这个过程中有很多值得优化的问题。本期文章将和大家聊聊,服务端的优化问题。
为了减少内存拷贝,提高读取吞吐,3FS 服务端的主要操作是:
- 使用 Direct IO 来做读取,减少了磁盘到 Page Cache 的拷贝
- 使用 AIO 接口提高读取吞吐
- 在客户端进行数据对齐,简化接口使用
Direct IO
Linux 提供两种文件 IO 模式,分别是 Buffered IO 和 Direct IO。Buffered IO 使用内核提供的 Page Cache 缓存磁盘上的数据,可以为多次访问的数据带来显着的性能优势。但对深度学习训练来说,每一次迭代读取的都是新数据,缓存失去意义,Page Cache 反而成为了负担。所以 3FS 服务端会默认使用 Direct IO 进行数据读取,绕开 Page Cache 以减少一次数据拷贝,直接从磁盘读数据到用户态内存,同时也规避了 Page Cache 的高内存占用。
AIO
AIO 是 Linux 提供的异步 IO 接口,它支持应用提交多个异步 IO 操作在后台并发执行,并在前端同步地等待操作完成。AIO 目前仅支持以 Direct IO 方式打开的文件。相较于传统的同步 IO 接口,AIO 可以在更低的 CPU 占用下提供更高的读写吞吐。幻方 AI 的深度学习训练框架中默认使用 AIO 接口进行训练样本数据的读取。此外,对于读取大小超过阈值的同步读取操作(阈值默认 1MB),3FS 的客户端会将其转为 AIO 操作以提高读取性能。同时我们也正在适配内核新提供的 io_uring 接口,相信可以带来进一步的性能提升。
对齐
Direct IO 在使用上有一个很大的限制,它需要 buffer 的内存地址、每次读取的 size 以及 offset 均与底层设备的逻辑块大小对齐,一般是 512 字节对齐。为了提高接口的易用性,3FS 的客户端会对 AIO 读取操作进行必要的对齐,它会在 buffer 的头部和尾部增加额外缓存以实现 512 字节对齐,并在 RDMA Read 接收数据时忽略掉头部和尾部。这样就实现了以下两种效果:
- 用户的 AIO 操作不再需要对齐,使用上更简单
- 用户的同步 IO 操作可以在客户端直接转为 AIO 操作而不需要考虑对齐和 O_Direct,提高性能
小结
本文介绍了幻方AI在设计3FS文件系统时,针对服务端优化的一些思考。我们采用 Direct IO 和异步对齐的读取方式,让服务端的数据加载更符合模型训练的使用场景,从而获得更好的读取性能。
3FS能跑出这样的性能也不是一蹴而就的,幻方AI在长期实践中对其不断优化,遇到了不少挑战。本系列文章将陆续为大家分享一些有关3FS性能优化的小故事,作为抛砖引玉,其中还不乏我们踩过的坑。欢迎业界的学者专家们一起探讨。