在上一篇中我们介绍了 mpi4py 中读/写文件中数组的方法,下面我们将介绍 mpi4py 中的非阻塞 I/O 操作。
MPI 支持前面介绍过的所有读/写方法(包括使用独立文件指针和显式偏移地址的读/写方法,非集合和集合读/写方法)的非阻塞版本。非阻塞读/写方法的名称一般是在对应的阻塞读/写方法的名称前面加上 I,如 Iread/Iwrite,Iread_at/Iwrite_at 等。非阻塞读/写方法和非阻塞通信方法一样,调用完后会立即返回一个 MPI.Request 对象,可以使用其 Test,Wait 等方法来检测或等待其完成。使用非阻塞 I/O 操作的一大优势在于可以潜在地重叠或部分重叠 I/O 操作和同时发生的计算和通信。
非集合操作
下面是非集合的非阻塞读/写方法的使用接口,它们和对应的阻塞版本有几乎完全一样的参数(少了 status
参数,实际上是将 status
参数转移到了其返回的 MPI.Request 对象的相关方法上)。调用这些非阻塞方法会立即返回一个 MPI.Request 对象,其返回并不意味着本次 I/O 操作已经完成,必须使用其返回的 MPI.Request 对象的 Test,Wait 及其变种等方法来检测和等待其完成。
非阻塞独立文件指针读/写
MPI.File.Iread(self, buf)
MPI.File.Iwrite(self, buf)
非阻塞显式偏移地址
MPI.File.Iread_at(self, Offset offset, buf)
MPI.File.Iwrite_at(self, Offset offset, buf)
分步集合操作
对集合 I/O 操作,MPI 3.1 之前的版本只支持一种称作分步集合 I/O (split collective I/O) 的非阻塞集合 I/O 方法。这是一种带有一定限制性的非阻塞 I/O 操作。之所以称作分步集合 I/O,是因为其把集合访问文件拆分成了两个动作——启动集合访问和结束集合访问。要使用这种 I/O 称作,用户必须先调用一个 “begin” 方法,如 Read_all_begin,来启动集合 I/O 操作,然后在合适的地方调用一个匹配的 “恩典” 方法,如 Read_all_end,来完成该 I/O 操作。这种集合操作的限制在于,进程在某一时刻对某个文件句柄只允许有一个分步集合 I/O 操作处于活动状态。即使使用多线程,也不允许一个进程内同时有两个线程对同一个文件句柄并发地执行两个或更多个分步集合操作。也就是说当在某个文件句柄上调用了一个分步集合 I/O 的 “begin” 方法后,在没有调用其匹配的 “end” 方法结束该分步集合 I/O 操作之前,不能再在这个文件句柄上调用第二个分步集合 I/O 的 “begin” 方法。由于这一限制,一个分步集合 I/O 操作的 “begin” 方法不返回 MPI.Request 对象,也不返回其它结果(实际上其返回指为 None)。其紧接着的在同一个文件句柄上调用的 “end” 方法会匹配该分步集合 I/O 的 “begin”方法。MPI 标准允许 MPI 实现在 “begin” 调用时完成整个 I/O 操作,或是在 “end” 调用时完成整个 I/O 操作,也或者是在 “begin” 和 “end” 之间完成。另外,因为这些方法都是集合操作,因此必须由打开文件的进程组中的所有