"文件名是什么?是否要后缀?"——没有洞或强制要求,至少MPI2.2标准文档没有说有限制
刚接触MPI,说说自己的看法。
文件读取和初始化 *** 作可以在MPI_Init之前执行的。建议核心函数还是放在MPI结构中辩拦衫。如
void preProcess()//执行文件读取和初始衡桥化携腔 *** 作MPI_Init(&argc,&argv)
...
core(*,*,*...)//参数中应该含有进程id,这样core函数就并行化了
...
其实文件读取和初始化 *** 作也是可以并行实现的,目前还不会。
在 上一篇 中我们介绍了 mpi4py 中的文件互 *** 作性,下面我们将介绍 mpi4py 中获得高性能 I/O 的方法和建议。
MPI 在底层实现中可充分利用集合 *** 作和非连续数据读/蚂简咐写进行面向文件系统/设备的特殊优化。因此使用 MPI I/O *** 作,最重要的就是要活用其提供的几个特征:单次非连续数据访问,集合 *** 作,非阻塞 *** 作,理解并灵活设置适合文件系统特征的各 hint,等。
由于底层可能提供的优化措施,应尽量使更多的进程参与 I/O *** 作而不是将其集中在一个进程上。对非连续 I/O,应定义相应的派生数据类型描述“非连续性”,进而再利用集合 *** 作让多个进程一起提交数据 I/O 请求。通常情况下应用程序都有自己的计算模式进而也可找出其 I/O 访问特征,要针对不同的 I/O 特征结合底层硬件设计相应的执行模型。对相同的 I/O 访问特征,也能以不同的发起方式提交给 I/O 系统,比如说使用哪一个具体的读/写方法及怎样调用该读/写方法等。
一般可以将 I/O 访问模式分为 4 个级别。
我们以一个具体的例子来讲解这四个不同的访问级别。考虑一个以块状形式分布在16 个进程上的二维数组,具体的分布情况如下图所示:
这个数组作为一个整体以行优先的顺序存储在一个文件中,如上图所示,文件中首先是 0 号进程本地子数组的第一行,紧接着是 1 号进程本地子数组的第一行,然后是 2 号进程本地子数组的第一闷纯行,然后是 3 号进程本地子数组的第一行,接下来是 0 号进程本地子数组的第二行,1 号进程本地子数组的第二行,等等。现在每个进程要从这个文件中读取该进程本地的数据。可以看出,每个进程的本地数据都是以不连续的小块方式存储于文件的不同位置。
对这个例子,4 个级别的访问模式分别为:
级别 0:各个进程按照类似 Unix/Linux 中 I/O *** 作方式独立地一次读取本地子数组的一行。具体来说,像下面这样:
级别 1:基本同级别 0,不过采用集合 I/O *** 作。具体来说,像下面这样:
级别 2:各个进程定义派生数据类型作为 filetype 描述数据分布方式,然后独立访问自己负责的数据块。具体来说,像下面这样:
级别 3:基本同级别 2,不过采用集合 I/O *** 作。具体来说,像下面这样:
这 4 个级别的访问模式代表着逐步更多数据量的单次 I/O 请求,就像下图所示:
每次 I/O 请求的数据量越大,MPI 实现就有更大的机会来产生更高的性能。因此只要可能,用户应该尽量使用级别 3 的数据访问模式。
当应用程序的每个进程只需要访问文件中单独一整块连续的数据,级别 0 和级别 2 将变的等价,级别 1 和级别 3 也等价,此时用咐宴户没有必要定义派生数据类型,直接使用级别0 或级别 1 也能取得高的性能。
有了上述讨论的访问特征信息,MPI IO 的底层实现可实施如下优化:
下面给出使用例程。
运行结果如下:
以上介绍了 mpi4py 中获得高性能 I/O 的方法和建议,在 下一篇 中我们将介绍 mpi4py 并行读/写 numpy npy 文件的方法。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)