1.10 MPI开发心得
与其他的编程方法一样,MPI编程需要了解MPI特性,只有掌握MPI编程方法的优点和缺点,才能编写高效的MPI程序。对MPI最重要的认识是MPI属于一种函数库。MPI操作需要至少调用一个或多个MPI函数,针对特别少量的数据传输,MPI编程方法的效率可能不是最高的。因此,若使用MPI编程,在每次数据通信中需传输尽可能多的数据,从而提高通信效率。
MPI支持用户构建自己的软件库。相对于在程序中调用MPI函数,利用MPI在程序中实现自定义接口的方法更好。很多应用程序采用自定义接口的方法,从而程序代码显得更加整洁。很多重要的计算库和框架均采用自定义接口的方法,如PETSc [26,229]和Trilinos [137]。在上述函数库中,很少直接调用MPI函数,即使出现MPI函数调用,一般只出现在用户代码中。
内存访问局部性对计算性能有较大影响。MPI程序基于进程运行,可帮助用户维护内存数据的局部性。该特性既是MPI的优势,有时也会成为劣势。优势在于要求用户实现数据局部性,从而提高程序运行效率。劣势在于用户必须实现内存数据局部性要求。在内存访问上实现数据局部性,尤其在缓存和主要内部存储器间,对开发高效率的并行程序非常重要。
并行程序运行性能和结果往往与期待的不同,因此采用相关工具对性能和结果进行测试是非常必要的。MPI调试接口可为程序调试和性能测试提供帮助,协助开发人员分析MPI程序[23,72,145,300]。用户也可利用MPI调试接口,分析程序性能,设计高效率的并行程序。
在使用MPI过程中,存在一些使用心得,如下所示:
(1)认真检查和使用内存缓冲区。(参考安全程序设计讨论。)
(2)避免不必要的同步操作。避免在数据通信过程中使用不必要的同步操作,例如在非阻塞式通信方式中采用等待多个非阻塞式通信操作完成的函数(例如,MPI_Waitall)。
(3)在数据通信量从少量增加到中等规模时(数据通信量大小取决于网络、CPU和MPI实现方式),建议使用连续的MPI通信,从而减少MPI通信过程中的开销。
(4)在MPI程序中,尽量采用通过MPI构造的数据类型,减少非连续数据的内存移动操作,提高MPI程序运行效率。
(5)在I/O访问中,尽量采用聚合I/O。但在采用聚合I/O过程中,需要注意文件系统限制(例如,一些文件系统不支持数据块边界对齐)。
(6)MPI_Barrier函数对程序性能有较大影响,不建议采用。在文献[252]中,提供一种自动检测不必要同步操作的方法。除非一些特殊情况,MPI_Barrier函数通常在MPI程序中很少使用,若经常使用MPI_Barrier函数则将极大影响程序性能,是一种不正确的MPI编程方法。