MPI编程模式

                                      MPI编程

 

3.1 MPI简介

多线程是一种便捷的模型,其中每个线程都可以访问其它线程的存储空间。因此,这种模型只能在共享存储系统之间移植。一般来讲,并行机不一定在各处理器之间共享存储,当面向非共享存储系统开发并行程序时,程序的各部分之间通过来回传递消息的方式通信。要使得消息传递方式可移植,就需要采用标准的消息传递库。这就促成的消息传递接口(Message Passing Interface, MPI)的面世,MPI是一种被广泛采用的消息传递标准[1]。

与OpenMP并行程序不同,MPI是一种基于消息传递的并行编程技术。消息传递接口是一种编程接口标准,而不是一种具体的编程语言。简而言之,MPI标准定义了一组具有可移植性的编程接口。各个厂商或组织遵循这些标准实现自己的MPI软件包,典型的实现包括开放源代码的MPICH、LAM MPI以及不开放源代码的Intel MPI。由于MPI提供了统一的编程接口,程序员只需要设计好并行算法,使用相应的MPI库就可以实现基于消息传递的并行计算。MPI支持多种操作系统,包括大多数的类UNIX和Windows系统。

3.1.1如何实现MPI

MPI是一个标准。它不属于任何一个厂商,不依赖于某个操作系统,也不是一种并行编程语言。不同的厂商和组织遵循着这个标准推出各自的实现,而不同的实现也会有其不同的特点。MPICH是影响最大、用户最多的MPI实现。目前可下载的最新的MPICH软件包为MPICH1.2.7pl和2008年2月15日发布的MPICH 2-1.0.7测试版(我使用的是MPICH 2-1.0.6pl),在http://www.mcs.anl.gov/research/projects/mpich2/index.php可以下载到,分别有支持UNIX和Windows的32位和64位版本。

3.1.2 MPI程序的特点

MPI程序是基于消息传递的并行程序。消息传递指的是并行执行的各个进程具有自己独立的堆栈和代码段,作为互不相关的多个程序独立执行,进程之间的信息交互完全通过显示地调用通信函数来完成。

3.2 MPICH的安装和配置

我使用的MPICH2安装文件是mpich2-1.0.6p1-win32-ia32.msi,在Windows下安装MPICH2比较简单,但是要有Microsoft .NET Framework 2.0的支持。安装基本上只要单击“Next”即可。在安装过程中会提示输入进程管理器的密码,这个密码被用来访问所有的程序,这里使用的密码为admin。

安装完成后,安装目录下的include子目录包含了编程所需要的所有头文件,lib子目录包含了相应的程序库,而子目录bin则包含了MPI在Windows下面必须的运行程序。运行时需要的动态链接库被安装在了Windows系统目录中。在Windows平台下可以使用Microsoft Visual Studio来开发MPI程序,下面举例说明。

首先,新建一个Win32控制台项目,然后将MPICH2安装目录下的include

 

图3-1 配置头文件目录

 

子目录加入到头文件目录中。在VS 2005的菜单 工具->选项->项目解决方案->VC++目录对话框中添加include子目录,如图3-1所示。再用相同的方法将MPICH2\lib加入到库文件目录中,如图3-2。

 

图3-2 配置库文件目录

 

为了避免名字冲突,需要在预编译头文件stdafx.h中加入#inlcude mpi.h语句。现在就可以在主程序文件中编写MPI程序了,MPI的开发环境配置完毕。

3.3 在Windows下如何运行MPI程序

我所进行的MPI程序的开发均是在Windows平台下,使用Visual Studio 2005 + MPIEXEC wrapper 进行的,首先用一个简单的Hello World 程序说明运行环境的配置。

按照上一小节介绍配置好开发环境之后,在VS 2005中新建立一个Win32 控制台项目,并取名MPI1,在MPI1.CPP文件中输入下面的程序。在项目属性的“配置属性”->“常规”项中的“字符集”设置为“未设置”,如图3-3所示。

例3_1

int _tmain(int argc, _TCHAR* argv[])

{   int rank, size;

       MPI_Init(&argc, &argv);

       MPI_Comm_rank(MPI_COMM_WORLD, &rank);

       MPI_Comm_size(MPI_COMM_WORLD, &size);

       printf("Hello World from thread %d of %d\n", rank, size);

       MPI_Finalize();

       return 0;

}

这个程序比较简单,在函数MPI_Init()和MPI_Finalize()之间是程序并行执行的地方,MPI_Init()、MPI_Comm_rank()、MPI_Comm_size()和MPI_Finalize(),这四个函数是MPI中最重要和最常用的函数。下面分别说明:

 

图3-3 配置项目属性

(1)    MPI_Init和MPI_Finalize

MPI_Init用来初始化MPI执行环境,建立多个MPI进程之间的联系,为后续通信做准备。而MPI_Finalize则是结束MPI执行环境。这两个函数就是定义MPI程序的并行区的,除了检测是否初始化的函数之外,不应该在这两个函数定义的区域外调用其它MPI函数。这两个函数都返回整型值,标识函数是否调用成功。

(2)    MPI_Comm_rank

MPI_Comm_rank函数就是用来标识各个MPI进程的,给出调用该函数的进程的进程号。MPI_Comm_rank返回整型的错误值,需要提供两个参数:

l        MPI_Comm类型的通信域,标识参与计算的MPI进程组。上面例子中使用的是MPI_COMM_WORLD,这个进程组是MPI实现预先定义好的进程组,指的是所有MPI进程所在的进程组。如果想要申请自己的特殊的进程组,则需要通过MPI_Comm定义并通过其它MPI函数生成。

l        &rank返回调用进程中的标识号。

MPI还定义了另一个进程组MPI_COMM_SELF,只包含各个进程自己的进程组。

(3)    MPI_Comm_size

这个函数则用来标识相应进程组中有多少个进程,它也有两个参数:

l        MPI_Comm类型的通信域,标识参与计算的MPI进程组。上面的例子中用的是MPI_COMM_WORLD。

l        &size返回相应进程组中的进程数。

运行这个程序,运行结果如图3-4,按照并行执行的方式,上面程序运行结果应该打印两行文字信息,为:

Hello World from thread 0 of 2

Hello World from thread 1 of 2

 

 

图 3-4 例3_1在windows上的运行结果

(本机系统环境变量OMP_NUM_THREADS值是2),但是运行结果确只打印了一行,显然函数MPI_Init和MPI_Finalize之间的代码仅被一个线程串行执行了。经过查询资料知道,MPI程序若要被正确运行需要使用MPICH2安装目录下的运行工具MPIEXEC wrapper运行用VS 2005生成的exe文件。启动这个程序,程序的界面如图3-5

 

 

图 3-5 MPIEXEC wrapper程序界面

由于该程序只有操作系统的管理员才有权使用,所以在第一次运行时需要输入计算机用户名和口令,并且不允许口令为空,如图3-6。输入完毕后,单击“Register”按钮完成注册,之后就可以使用该工具运行MPI程序了。

在“Application”栏中选择要运行的exe程序,在“Number of process”栏中选择要运行程序的线程数,然后单击“Execute”按钮运行程序。如用4线程运行上面的示例程序,输出结果如图3-7所示。

 

             图 3-6 输入系统用户名和口令

 

图 3-7 使用MPIEXEC wrapper运行例3_1的结果

 

4线程分别执行MPI_Init和MPI_Finalize之间的代码,打印4行信息,程序执行结果正确。

3.4 MPI的点对点通信

点对点通信是MPI程序的基础,MPI_Send和MPI_Recv是两个最重要的函数。这两个函数的标准形式是:

l        int MPI_Send(buf, counter, datatype, dest, tag, comm)

参数作用如下:

    buf:发送缓冲区的起始地址,可以是数组或结构指针

    count:非负整数,发送的数据个数

    datatype:发送数据的数据类型

    dest:整型,目的的进程号

    tag:整型,消息标志

    comm:MPI进程组所在的通信域

这个函数返回整型的错误码,它的含义是向通信域中的dest进程发送数据,数据存放在buf中,类型是datatype,个数是count,这个消息的标志是tag,用以和本进程向同一目的进程发送的其它消息区别开来。

l        int MPI_Recv(buf, count, datatype, source, tag, comm, status)

参数作用如下:

    buf:接收缓冲区的起始地址,可以是数组或结构指针

    count:非负整数,最多可接收的数据个数

    datatype:接收数据的数据类型

    source:整型,接收数据的来源,即发送数据进程的进程号

    tag:整型,消息标识,应与发送操作的消息标识相同

    comm:消息接收进程所在的通信域

    status:MPI_Status结构指针,返回状态信息

这个函数返回整型的错误码,它的含义是进程从comm域中source进程接收标签号为tag的数据,并保存到buf中。接收缓冲区buf的大小不能小于发送过来的消息的长度。否则会由于数组越界导致程序出错。参数status是MPI_Status类型的,status主要显示接收函数的各种错误状态。通过访问status.MPI_SOURCE、status.MPI_TAG和status.MPI_ERROR就可以得到发送数据的进程号、使用的标签以及接收操作的错误代码。另外,还可以使用函数MPI_Get_count来获得实际接收到的数据项数。MPI_Get_count的标准定义为:int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count);将实际接收到数据项数存放到count中。下面用一个程序说明上面提到的函数的使用方法。

示例程序见例3_2

程序的运行结果如图3-8(4个进程)

函数MPI_Get_processor_name用于获得计算机名,并存放在processor_name中,长度为namelen,宏定义MPI_MAX_PROCESSOR_NAME是机器名的最大长度。这个程序的完成的任务是使进程i发送数据给进程i+1,并等待由进程i-1发送来的数据。最后一个进程则发送数据给进程0。

3.5统计时间函数

为了验证程序并行化后的效果,MPI提供了两个用于统计时间的函数 MPI_Wtime和MPI_Wtick。其中MPI_Wtime返回一个双精度数,表示从过去某点的时刻到当前时刻所消耗的时间秒数。而函数MPI_Wtick则返回MPI_Wtime结果的精度。修改例3_2程序,在并行代码两端加入统计时间的函数,如例3_3:

例 3_3(完整程序见示例程序4_3)

       begin = MPI_Wtime();

       end = MPI_Wtime();

       diff = end - begin;

       printf("%d process time is %9.7f\n", myid, diff);

       printf("%d process tick is %9.7f\n", myid, MPI_Wtick());

}

运行结果如图3-9:

 

 

图 3-8 例3_2的运行结果

 

 

图 3-9 例3_3的运行结果

3.6负载均衡对程序性能的影响

在并行计算中,如果各个处理器上的工作所需要的完成时间不同,则会使先完成工作的处理器等待未完成工作的处理器,浪费了计算资源。这时应该使各个处理器的负载尽量均衡。一般采用的策略有两种:静态负载平衡和动态负载平衡。前者适用于计算前可以准确知道负载,而且这些负载容易平均划分给各个进程的情况。而对于事先不知道负载情况,或者总负载不易划分的情况,则需要采用动态负载划分来解决。在动态负载平衡模式中存在一个管理结点负责给各个进程分配任务,当一个进程完成当前的计算任务后,它就向管理结点申请新的任务,如果还有未分配的任务,管理结点就将任务分配给那个进程,这有点类似于计算机硬件向CPU发中断请求服务的方式。

3.7 开发实例

下面将在Windows平台上使用MPI编写一个用数值积分法计算圆周率的程序。利用公式PI=

 

的近似值计算圆周率[7],定积分的计算可以转化为求一个曲边梯形的面积问题。将积分区间等分成n个小的子区间,可将每个小的子区间上的曲边梯形近似地看成矩形,这些矩形面积的和就近似地等于原来曲边梯形的面积。这样最终将求圆周率的问题转化成了一个面积迭加的计算。每个小矩形的宽为

 

(n为将积分区间等分的份数),高可以将x值带入函数

 

求得。用循环将每个小矩形的面积累加起来便是PI的近似值。具体的算法实现见附加中的程序“mpi_pi”。图3-10、3-11分别是用一个进程和两个进程运行的结果。

 

图3-10 使用一个进程的运行结果

图3-11 使用两个进程的运行结果

从运行结果可以看到使用两个进程时的计算速度反而不如用一个进程运行时的速度,这时由于本程序的计算规模不大,另外引入一个进程的开销大于程序并行所带来的益处,所以进程数越多反而程序的运行速度越慢。看下面一组数据[8](表3-1)

计算机数

计算时间

1

1.63643

2

0.83180

3

0.55622

这组数据是在不同的硬件平台下实现本开发实例程序的计算时间。运行环境为3 台计算机组成的集群, 配置均为CPU : Intel PentiumIII 733MHz,相同的算法,随着参与计算的机器数增加,计算时间减少。

MPI是针对分布式计算机系统提出的,它采用非共

表3-1                享内存的方式利用多进程完成并行任务,当计算规模不大或处理器数量不多时,更多进程的维护会增加系统的开销,而且进程之间的通信存在延时。它比较适合集群计算机系统。

3.8 小结

本章对MPI编程进行了初步研究,介绍了MPI程序的特点、软件包的安装、MPI程序的运行方式。

MPI是一种基于消息传递的并行编程技术,而不是一种具体的编程语言。MPI程序与OpenMP程序的最大不同就是MPI程序不仅可以适用多线程的方式并行运算还可以让程序以多进程的方式执行,以这种方式执行的程序并不共享内存,各个进程是通过消息传递来进行通信的。这样做的好处是完成某一计算任务的不同进程可以运行在不同处理器上(不只是处理器的不同核上),甚至是不同的结点计算机上,方便分布式计算系统的构建。在多核上使用MPI可以采用两种方式,一种是在多核平台上开发传统的多进程MPI并行程序,一个核执行一个MPI进程。另外一种方式是采用MPI + OpenMP的方法,在结点内采用多线程方式,结点间采用MPI多进程方式。

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中文版mpi编程手册 写得很详细 都志辉编著 李三立审阅 陈渝刘鹏 校对 本书介绍目前最常见的并行程序—MPI并行程序的设计方法它适合高校三四年级本科 生非计算机专业研究生作为教材和教学自学参考书也适合于广大的并行计算高性能计 算用户作为自学参考书使用对于有FORTRAN和C编程经验的人员都可以阅读并掌握 本书的内容 首先介绍了并行程序设计的基础提供给读者进行并行程序设计所需要的基本知识然 后介绍了MPI的基本功能从简单的例子入手告诉读者MPI程序设计的基本过程和框架 这一部分是具有C或/FORTRAN串行程序设计经验的人员很容易理解和接受的接下来介绍 MPI程序设计的高级特征是已经掌握了MPI基本程序设计的人员进一步编写简洁高效的 MPI程序使用各种高级和复杂的MPI功能所需要的最后一部分介绍了MPI的最新发展和 扩充MPI-2 主要包括三个部分动态进程管理远程存储访问和并行文件读写 本书包括了MPI-1的全部调用和MPI-2的关键扩充部分的调用并附以大量的图表和示 例性程序对程序的关键部分给出了讲解或注释读者若能将例子和对MPI调用的讲解结合 起来学习会取得更好的效果 本书的目的不仅是教给读者如何去编写从简单到复杂的MPI并行程序更重要的是 希望在学习本书之后在读者以后解决问题的过程中能够树立并行求解的概念使并行方 法真正成为广大应用人员和程序开发员手中的重要工具
### 回答1: 《并行计算_MPI编程手册》是一本详细介绍并行计算和MPI编程的参考书。MPI(Message Passing Interface)是一种并行计算的编程接口,它是一种消息传递模型,常用于高性能计算领域。 该手册的编写旨在帮助读者了解MPI编程的基本概念和使用方法。首先,它清晰地介绍了并行计算的概念,解释了并行计算的原理、优势和应用领域。然后,它详细介绍了MPI的基本概念和函数。通过该手册,读者可以学习如何在并行计算中使用MPI来实现高效的数据通信和协同计算。 此外,《并行计算_MPI编程手册》还包括了丰富的编程示例,这些示例涵盖了各种常见的并行计算问题,如矩阵乘法、并行排序和并行搜索等。通过这些示例,读者可以进一步了解MPI编程的应用技巧和调试方法。 此外,与许多其他MPI教材相比,《并行计算_MPI编程手册》也着重介绍了一些高级的MPI特性和技术,如进程拓扑结构、动态进程管理和集体通信等。这些内容对于那些希望进一步提高并行计算性能和扩展性的开发者来说尤其有用。 总而言之,《并行计算_MPI编程手册》是一本系统、全面的MPI编程参考书,适合那些对并行计算感兴趣的学者、研究人员和开发者阅读和参考。无论是初学者还是有一定MPI经验的人,都可以通过本书提供的知识来更好地理解和应用MPI编程。 ### 回答2: 《并行计算_MPI编程手册》是一本重要的参考书籍,介绍了MPI编程的相关知识和技术。MPI是一种消息传递编程模型,常用于并行计算领域。 本书分为多个章节,内容全面系统,对MPI的各个方面进行了详尽的介绍和讲解。首先,书中从MPI的基本概念开始,介绍了MPI的历史和发展,以及MPI的基本通信原语和常用函数。然后,书中详细解释了MPI的进程通信模式,包括点对点通信和集体通信。讲解了MPI的发送与接收操作,以及如何使用MPI实现消息发送和接收的功能。 此外,书中还介绍了MPI的进程拓扑结构和通信域的概念,包括拓扑创建函数、拓扑相邻通信函数等。对于MPI的进程管理和进程间同步问题,本书也进行了深入的探讨。对于MPI的性能优化和调试技巧,本书也提供了许多实用的建议和方法。 此外,《并行计算_MPI编程手册》还提供了丰富的编程案例和实例代码,帮助读者深入理解MPI编程的实际应用。除了介绍MPI的基本概念和实现细节外,本书还介绍了MPI的扩展功能和其他特性,如动态进程管理、远程内存访问等。 总之,《并行计算_MPI编程手册》是一本权威的MPI编程参考书籍,内容详实、全面,适合MPI编程初学者和专业人士使用。通过阅读本书,读者可以深入理解MPI编程模型,掌握MPI的基本原理和应用技巧,提高并行计算的效率和性能。 ### 回答3: 《并行计算_MPI编程手册.pdf》是一本介绍MPI(消息传递接口)编程的手册。MPI是一种用于实现并行计算的标准接口,它定义了一套函数库,可以在多个进程之间进行通信和同步操作,以实现分布式计算。这本手册对MPI的使用方法、编程技巧和最佳实践进行了详细的讲解和示例。 《并行计算_MPI编程手册.pdf》首先介绍了MPI的基本概念和设计原理,包括进程通信、拓扑结构、通信模式等。然后,它引导读者了解MPI编程的基本步骤,包括初始化MPI环境、创建通信域、发送和接收消息、同步操作等。同时,手册还介绍了MPI的高级特性,如集合通信、非阻塞通信和一致性操作,以及如何利用这些特性实现更高效的并行计算。 为了帮助读者更好地理解MPI编程,手册提供了丰富的示例代码和详细的解释。读者可以通过这些示例代码,学习如何使用MPI实现各种并行算法和应用,如矩阵乘法、排序、并行搜索等。此外,手册还介绍了一些MPI实现的优化技巧和调试工具,以提高MPI程序的性能和可靠性。 总之,《并行计算_MPI编程手册.pdf》是一本全面而系统地介绍MPI编程的参考资料。无论是初学者还是有一定经验的程序员,都可以从中学习到丰富的MPI编程知识和技巧。这本手册对于研究并行计算、高性能计算以及分布式系统的学者和工程师来说,都是一本不可或缺的宝典。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值