【应该了解的背景知识】
1、MPI知识--[比较熟悉]
2、VC/Visual Studio知识--[一般了解]
3、C++知识--[熟悉]
MPI全称消息传递接口,是Message Passing Interface的缩写,MPI是一个库,而不是一门语言。它是一种标准或规范的代表,而不特指某一个对它的具体实现。
本次实验过程中,使用的MPI实现是MPICH,MPICH是一种最重要的MPI实现,它可以免费从http://www-unix.mcs.anl.gov/mpi/mpich 取得,更为重要的是,MPICH是一个与MPI-1规范同步发展的版本,每当MPI推出新的版本,就会有相应的MPICH的实现版本。
MPICH的下载安装
可以从http://www-unix.mcs.anl.gov/mpi/mpich 免费下载得到MPICH的最新版本。本次实验使用的是MPICH2 for Microsoft Windows 版本是 1.0.3 ,下载后直接运行,安装即可。
MPICH的配置
本次实验使用的开发语言是C/C++,运行环境为Microsoft Windows XP Professional,开发工具为Microsoft Visual Studio 2005。安装完MPICH2后,要将MPI库添加到Visual Studio的库目录中,将inculde文件添加到Visual Studio的include目录中。具体步骤如下:
1. 单击“工具”菜单,选择“选项”,在弹出对话框中双击树型目录中的“项目和解决方案”,打开之。在其子目录里面选中“VC++目录”一项,此时右侧显示相应属性。
2. 在“显示以下内容的目录”下拉菜单中选择“库目录”,单击“新行”按钮(快捷键Ctrl+Insert),在新添加的行中单击最右侧浏览按钮,选择MPICH2的安装目录,然后选择lib子目录,选择“打开”,加入完成,如图:
3. 使用与第二步相同的方法,将“引用文件”添加上,如图:
4. 新建一个空白“Windows控制台应用程序”项目,假设命名为FFT,在“项目”菜单中选择“FFT属性”,在弹出对话框中依次开左侧树型列表的“配置属性”、“链接器”、“输入”,在“附加依赖项”一栏输入:mpi.lib,如图:
选择“配置”下拉列表中的release选项,同样将mpi.lib添加上去。(也可以使用#pragma预处理指令:#pragma comment(lib,"mpi.lib"))
程序运行与测试:
VC下将程序直接编译链接为exe文件,然后使用MPICH2附带的运行工具即可模拟运行并行程序。
在运行程序前,要对MPICH2的运行环境进行设置,本次实验仅使用一台计算机来进行模拟,所以,设置比较简单,使用开发包提供的wmpiregister即可。如果要同时使用多太计算机来运行,就要用到wmpiconfig工具来进行配置。两个工具都位于mpi安装目录下的bin目录中。这里,我们只介绍wmpiregister。wmpiregister运行界面如下:
程序的设置很简单,只要在Account中输入你当前登录Windows所使用的用户名,在password中输入该用户名对应的密码即可。MPICH2不能使用没有密码的用户,如果当前用户没有密码,则应该为其创建一个,然后再运行wmpiregister进行配置。输入完成后,单击Register进行注册即可。显示Password encrypted into the Registry,即表示注册成功。
MPICH2带有两个运行工具,第一个为mpiexec.exe,第二个为wmpiexec.exe,均位于mpi安装目录下的bin目录中。第一个为命令行工具,使用方法如下:
第2个参数为处理器个数,第4个参数为将要运行的程序。
第二个为Win32窗口程序,运行后界面如下:
其实这个程序仅仅是一个界面,最终程序仍然要调用mpiexec.exe来运行,所以两种方式本质上是相同的。这里更建议使用命令行方式,或在使用窗口方式时将“run in a separate window”勾中,因为经过多次实验,发现窗口方式运行时,输出显示是没有问题的,但是如果要向程序输入数据,在窗口模式下似乎行不通,估计mpiexec这个程序有问题。
MPI(Message Passing Interface)是消息传递并行程序设计的标准之一,当前通用的是MPI1.1规范。正在制定的MPI2.0规范除支持消息传递外,还支持MPI的I/O规范和进程管理规范。MPI正成为并行程序设计事实上的工业标准。
MPI的实现包括MPICH、LAM、IBM MPL等多个版本,最常用和稳定的是MPICH,曙光天潮系列的MPI以MPICH为基础进行了定制和优化。
MPICH含三层结构,最上层是MPI的API,基本是点到点通信,和在点到点通信基础上构造的集群通信(Collective Communication);中间层是ADI层(Abstract Device Interface),其中device可以简单地理解为某一种底层通信库,ADI就是对各种不同的底层通信库的不同接口的统一标准;底层是具体的底层通信库,例如工作站机群上的p4通信库、曙光1000上的NX库、曙光3000上的BCL通信库等。
MPICH的1.0.12版本以下都采用第一代ADI接口的实现方法,利用底层device提供的通信原语和有关服务函数实现所有的ADI接口,可以直接实现,也可以依靠一定的模板间接实现。自1.0.13版本开始,MPICH采用第二代ADI接口。
我们将MPICH移植到曙光3000高效通信库BCL(Basic Communication Library)上(简称MPI_BCL)。MPI_BCL的接口标准与MPICH版本1.1完全一致,满足MPI1.1标准。同时,也支持ch_p4的通信库,即利用TCP/IP通信机制。从网络硬件角度说,MPI_BCL针对系统网络,MPI_ch_p4针对高速以太网。
1.MPI的程序设计
MPI1.1标准基于静态加载,即所有进程在加载完以后就全部确定,直至整个程序结束才终止,在程序运行期间没有进程的创建和结束。一个MPI程序的所有进程形成一个缺省的组,这个组被MPI预先规定的Communicator MPI_COMM_WORLD所确定。
MPI环境的初始化和结束流程如下:在调用MPI例程之前,各个进程都应该执行MPI_INIT,接着调用MPI_COMM_SIZE获取缺省组(group)的大小,调用MPI_COMM_RANK获取调用进程在缺省组中的逻辑编号(从0开始)。然后,进程可以根据需要,向其它节点发送消息或接收其它节点的消息,经常调用的函数是MPI_SEND和MPI_RECV。最后,当不需要调用任何MPI例程后,调用MPI_FINALIZE消除MPI环境,进程此时可以结束,也可以继续执行与MPI无关的语句。
上面提到的六个函数:MPI_INIT,MPI_COMM_SIZE,MPI_COMM_RANK,MPI_SEND,MPI_RECV,MPI_FINALIZE 实际上构成了编写一个完整的MPI程序所需例程的最小集。
2.MPI的几个重要特征
下面分别介绍MPI的几个重要特征:Communicator(通信空间)、Group(进程组)、Context_id(上下文标识)、Data Types(数据类型)。
MPI提供Communicator来指定通信操作的上下文,提供了通信操作的执行空间。在某个通信空间(或上下文)中发送的消息必须在相同的空间中接收,不同空间中的消息互不干扰。定义一个Communicator,也就指定了一组共享该空间的进程,这些进程组成了该Communicator的Group。
Communicator通过其特征属性Context_id来区分,同一个进程不同的Communicator有不同的Context_id。因此Context_id是另一个区分消息的标志。
MPI引入消息的Data Type属性的目的有两个:一是支持异构系统计算;二是允许消息来自不连续的或类型不一致的存储区,例如,可以传送数组的一列,或传送一个结构值,而该结构的每个元素的类型不同。Data Types定义了消息中不连续的数据项及其可能不同的数据类型。Data Type由应用程序在执行时通过基本的数据类型创建。
3.消息
一个消息相当于一封信,消息内容相当于信本身,消息的接收者相当于信封上的内容。因此通常将前者称为消息的buffer, 后者称为消息的envelop。
buffer: message address, count, datatype;
envelop: process id, message tag,communicator
在MPI以前的大多数通信系统中,消息buffer通常仅由buffer的地址和长度决定(例如曙光1000上的NX通信系统),那么在MPI的消息格式中为什么要引入Data Type呢?这有两个主要原因:
支持异构计算:不同系统有不同的数据表示。解决这一问题的方法是预先定义一些基本数据类型,MPI实现过程中对这些类型进行转换,例如转换为XDR格式,接收时进行反转。
派生的数据类型(Derived Data Types):允许消息来自于不连续的和类型不一致的存储区域。
4.MPI应用程序的编译
Include文件
C语言应用程序应有
#include "mpi.h"
若使用cc编译,命令行应有:
-I/cluster/mpi/net/include (net版)
-I/cluster/bcl/include -I/cluster/rms/include -I/cluster/sdr/include -I/cluster/mpi/mesh/include (mesh版)
Fortran语言应用程序应有
include 'mpif.h'
若使用f77编译, 命令行应有:
-I/cluster/mpi/net/include (net版)
-I/cluster/bcl/include -I/cluster/rms/include -I/cluster/sdr/include -I/cluster/mpi/mesh/include (mesh版)
MPI库文件
C语言
C语言程序编译时需作下述链接:
-L/cluster/mpi/net/lib -lmpi -lbsd (net版)
-L/cluster/mpi/mesh/lib -L/cluster/bcl/lib -L/cluster/rms/lib -L/cluster/sdr/lib -lmpi -lbcl -lrms -lsdr (mesh版)
数学函数库还应链接: -lm
Fortran语言
Fortran编译时应作下述链接:
-L/cluster/mpi/net/lib -lmpi -lbsd (net版)
-L/cluster/mpi/mesh/lib -L/cluster/bcl/lib -L/cluster/rms/lib -L/cluster/sdr/lib -lmpi -lbcl -lrms -lsdr (mesh版)
mpif77和mpicc
MPI提供了两个工具(mpif77和mpicc)来简化MPI应用程序的编译。用户可以直接地使用命令行方式mpicc或mpif77来编译C或Fortran程序,编译方式与cc和f77完全一致。如:
mpif77 -c foo.f
mpicc -c foo.c
mpif77 -o foo foo.o
mpicc -o foo foo.o
有时链接时需一些特殊库, 应在链接时注明。使用mpicc和mpif77省略了有关MPI的路径设置。
5.MPI应用程序的运行
应用程序编译好后,使用mpirun命令运行MPI应用程序。mpirun命令完整的格式如下:
mpirun [-h|-?|-help] [-sz size|-sz hXw] [-np nprocs] [-pl poolname]
各个选项的值由用户从命令行中显示地指定,选项的含义如下:
-h
-?
-help:显示帮助信息。
-sz
指定物理节点的数目。有两种指定形式,一是直接指定size值,另一种是指定物理节点的矩形域的长和宽。size值和h*w的值如果超过所在pool的节点数,sz项的值取pool的节点数,h*w值取整个pool。两者的缺省值分别为所在pool的节点数和整个pool。
-np
用户期望运行的进程数。进程数与实际申请的物理节点数没有任何联系,因为允许一个节点上运行同一个应用的多个进程。如果未指定,取实际sz项的值。
-pl poolname
应用程序执行的pool。应用程序的每次执行能且只能在一个pool中执行。缺省值为系统为用户设置的缺省的pool名(每个用户在创建时已自行指定或系统分配了一个缺省的pool)。
在运行选项后,是用户的程序名。该可执行文件必须在所指定的或缺省的pool中的所有节点上能找到,并且与启动节点上的路径一致。用户程序名后的一切字符串都视为其参数(不包括被shell解释的重定向等,对shell解释的一些特殊字符,如需作为参数,应作相应的转换)。因此运行选项与用户程序名有先后的顺序,先运行选项,后用户程序名和参数。