在高性能计算中,经常会用到MPI或者MPI-IO,那MPI和MPI-IO到底是什么呢?
MPI(Message Passing Interface),是开发者们在高性能计算程序中,用于在参与计算的不同CPU、或服务器节点之间进行消息传递的一组规范或接口,通过这组接口,能帮助开发工程师们在不同的计算平台上快速编写可跨平台移植的并行计算程序,提升开发效率。基于MPI的规范和接口,业界有不同的MPI实现,如OpenMPI等。在高性能计算的世界中,除了计算,还必须有数据读写的支撑,所以除了MPI,还需要有一组跨计算平台的、可移植的、并行数据读写接口,这就是MPI-IO设计的初衷:让IO能够像消息传递(MPI)那样,通过标准的接口实现并行的数据读写访问。
说到IO接口,我们可以用下图来描述高性能计算程序是如何通过系统接口来访问数据的:
整个IO软件栈为用户和开发工程师们提供了标准的编程接口,以便大家在不需要关心底层存储硬件细节的情况下,通过标准的方式访问数据。
基础IO接口
整个IO栈中的最底层的接口是POSIX接口,它涉及最基本的文件操作,如open、close、read、write、stat等。POSIX HPC IO扩展的设计目的,是提高POSIX在大规模HPC环境中的性能,有意思的是,在大规模HPC环境中,对数据访问的性能要求有时会超过对数据一致性的要求。例如,相对于POSIX相当严格的一致性语义而言,HPC IO扩展对一致性的要求会显得放松一些。一般来说,大多数普通应用程序的API都是在POSIX语义之上构建的。
在整个IO栈中,最底层的是文件系统本身。文件系统管理着应用程序如何对硬件资源进行访问,同时,文件系统实现了POSIX API所需的功能。文件系统有两个极为关键的角色:
组织和维护文件命名空间
存储文件内容及文件的附加属性
在HPC环境中,我们通常可能会用到网络文件系统(NFS)和并行文件系统。NFS必须解决的两个问题是:
NFS Server如何协调多个客户端共享访问数据
在横向扩展的存储系统中,协调多个服务器的文件操作
标准的NFS Server通常只提供相当有限的并行访问能力,即单个客户端通过单一访问入口来访问数据,因此在HPC中使用并行IO策略时,难以提供足够高的性能。因此,在大型并行计算应用中,通常不使用NFS来进行数据访问。并行文件系统通常将单个文件数据分布在多个存储服务器上,而运行在多个计算节点上的并行应用程序的多个任务,经常对单个文件同时发起并发访问请求。并行文件存储系统可以通过并行的多个IO访问请求,为单个文件提供高水平的读/写带宽。
MPI-IO中间件
在HPC系统中,IO软件栈的中间件通常由MPI-IO的软件类库提供。应用程序可以通过使用MPI-IO提供的缓存和数据过滤技术,来整体提升数据访问性能,例如,ROMIO就是MPI-IO标准中比较常见的实现。
上层IO库
IO栈中还包括更高级别的一些类库,这些类库的API有助于工程师以更灵活的方式表达科学模拟计算,例如多维数据、标签和标记、非连续数据和分类数据。高性能计算程序的读写操作基于MPI-IO层之上,可以充分利用MPI-IO对数据读写的优化特性。这些上层IO类库甚至可以实现数据的可视化和简单的分析功能,同时能够在不同平台上实现移植,从而让这些高性能应用程序可以快速地在不同平台上运行。HDF5和NetCDF是目前使用较多的上层IO类库。在过去几年中,也有不少HPC用户开始选择PnetCDF和ADIOS来编写并行IO程序。
上面介绍的类库和接口都使用共享文件系统的方式实现并行IO,允许多个进程写入同一逻辑文件。
简单而言,MPI-IO利用了MPI的消息传递机制,基于POSIX语义,提供了一套为高性能计算访问数据的接口规范,不同的MPI-IO类库提供了不同的MPI-IO实现,而MPI-IO的实现的核心,是底层文件系统中各种POSIX语义的支持。YRCloudFile对POSIX语义的全面支持,也可以为不同的MPI-IO类库提供对底层文件系统的访问,从而支持高性能计算的各种应用。