目前windows下mpi实现版本已经由微软负责,软件名为msmpi。而原来mpi标准团队的windows下的mpich2实现已经很久没有更新了,当然使用以前下载的mpich2来构建mpi并行程序是没有问题的,但如果要使用mpi-3的一些新特性,那么就需要使用微软提供的msmpi。msmpi可以与intel,pgi编译器配合使用,但这些编译器都不是开源的,那么能否使用开源的gnu编译器呢?答案自然是可以的。
构建mpi并行程序主要是两种语言c/c++和fortran。其中c/c++程序的构建要简单很多,fortran则比较复杂。windows系统也分32位和64位系统,两种环境也存在差别,先将一一介绍。
mingw的gcc编译系统是一整套的编译器,包含gcc,g++,gfortran等分别编译c,c++,fortran程序。
下载一套mingw,地址:mingw。不用安装,直接解压到某个位置,把mingw下的bin目录加入环境变量。
msmpi是微软提供的mpi实现。介绍?
下载msmpi,地址:msmpi
安装两个文件后,打开cmd窗口,输入set MSMPI
可以看到安装路径,如果有如下输出,表示已经安装成功。
32位系统下:
MSMPI_BIN=C:\Program Files\Microsoft MPI\Bin\
MSMPI_INC=C:\Program Files\Microsoft SDKs\MPI\Include\
MSMPI_LIB32=C:\Program Files\Microsoft SDKs\MPI\Lib\x86\
MSMPI_LIB64=C:\Program Files\Microsoft SDKs\MPI\Lib\x64\
64位系统下:
MSMPI_BIN=C:\Program Files\Microsoft MPI\Bin\
MSMPI_INC=C:\Program Files (x86)\Microsoft SDKs\MPI\Include\
MSMPI_LIB32=C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\
MSMPI_LIB64=C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x64\
最终要实现对代码的编译,因此需要准备简单的测试程序代码,分c,c++,fortran代码如下:
#include "stdint.h" //重点是这一句
#include "mpi.h"
#include
#include
void main(argc,argv)
int argc;
char *argv[];
{
int myid, numprocs;
int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Get_processor_name(processor_name,&namelen);
fprintf(stderr,"Hello World! Process %d of %d on %s\n",myid,numprocs,processor_name);
MPI_Finalize();
}
#include "stdint.h" //重点是这一句
#include "mpi.h" //
#include
int main(int argc,char* argv[])
{
int myid, numprocs;
int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Get_processor_name(processor_name,&namelen);
std::cout<<"Hello World! Process"<
program hello_parallel
use mpi
!implicit none
!include 'mpif.h'
integer::procs,rank,ierr
character(MPI_MAX_PROCESSOR_NAME)::host
integer::hostlen
call MPI_INIT(ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,procs,ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr)
call MPI_GET_PROCESSOR_NAME(host,hostlen,ierr)
print '(a,i3,a,i4,a,a)','hello mpi&fortran from rank',rank,' of ',procs,' processes on ',trim(host)
call MPI_FINALIZE(ierr)
end program
测试环境包括32位和64位windows7系统,可以直接安装在电脑上或者在虚拟机中。
在安装完成软件并准备好程序代码之后,我们开始进行测试,注意到一般情况下,c和c++的mpi程序代码中会仅包含mpi.h头文件用于处理MPI函数。如果是这样的话,直接进行编译,那么会提示错误:
error: '__int64'
does not name a type; did you mean '__divtc3'?
typedef __int64 MPI_Aint;
这是因为__int64未定义,这个问题有两种方法解决:
解决了这个问题以后,那么就可以正常的进行编译和运行了。
c程序的编译命令和运行命令为:
gcc -o hello.exe hello.c -l msmpi -L "C:\Program Files\Microsoft SDKs\MPI\Lib\x86" -I "C:\Program Files\Microsoft SDKs\MPI\Include"
mpiexec -n hello.exe 3
结果为:
Hello World! Process 0 of 3 on PC-20171009XBQH
Hello World! Process 1 of 3 on PC-20171009XBQH
Hello World! Process 2 of 3 on PC-20171009XBQH
c++程序的编译和运行命令类似:
g++ -o hello.exe hello.cpp -l msmpi -L "C:\Program Files\Microsoft SDKs\MPI\Lib\x86" -I "C:\Program Files\Microsoft SDKs\MPI\Include"
mpiexec -n hello.exe 3
结果为:
Hello World! Process 0 of 3 on PC-20171009XBQH
Hello World! Process 1 of 3 on PC-20171009XBQH
Hello World! Process 2 of 3 on PC-20171009XBQH
fortran程序的编译要复杂很多,根据miroi的研究表明,不能直接进行编译,源代码中包含的文件也不是mpif.h,而需要使用mpi模块,该模块需要手动编译。并且因此,需要利用dlltool工具重新生成一个静态链接库,而不是使用原来的msmpi.lib。步骤如下:
复制msmpi库目录下的mpi.f90文件到存放源代码的当前目录下改名为mpi.F90,复制库目录下x86目录的mpifptr.h到当前目录下,进入命令行,采用如下命令编译:
gfortran -c -D INT_PTR_KIND()=8 -fno-range-check mpi.F90
其中INT_PTR_KIND()=8是因为fortran中没有INT_PTR_KIND()定义,所以这里直接指定,还有用-fno-range-check消除长整数的问题。
编译得到mpi.mod,mpi_base.mod,mpi_constants.mod,mpi_sizeofs.mod等文件,fortran源代码中只要价值mpi模块即可。
复制系统32位库目录下的msmpi.dll到当前目录下,利用gendef工具得到其中的函数信息:
gendef msmpi.dll
得到msmpi.def,接着利用dlltool工具生成一个libmsmpi.a的链接库,dlltool工具mingw套件里面有提供,命令为:
dlltool -d msmpi.def -l libmsmpi.a -D msmpi.dll
得到libmsmpi.a文件。
现在所有的准备都已经完成,利用gfotran和生成的链接库进行编译:
gfortran -o hello.exe hello.f90 libmsmpi.a -D INT_PTR_KIND()=8 -fno-range-check
运行使用mpiexec命令:
mpiexec -n hello.exe 3
结果为:
hello mpi&fortran from rank 1 of 3 processes on PC-20171009XBQH
hello mpi&fortran from rank 2 of 3 processes on PC-20171009XBQH
hello mpi&fortran from rank 0 of 3 processes on PC-20171009XBQH
64位系统下的c/c++程序编译与32位下类似,只是需要把库文件的路径修改一下,因此编译命令为:
c程序的编译命令和运行命令为:
gcc -o hello.exe hello.c -l msmpi -L "C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x64" -I "C:\Program Files (x86)\Microsoft SDKs\MPI\Include"
mpiexec -n hello.exe 3
结果为:
Hello World! Process 0 of 3 on PC-20171009XBQH
Hello World! Process 1 of 3 on PC-20171009XBQH
Hello World! Process 2 of 3 on PC-20171009XBQH
c++程序的编译和运行命令类似:
g++ -o hello.exe hello.cpp -l msmpi -L "C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x64" -I "C:\Program Files (x86)\Microsoft SDKs\MPI\Include"
mpiexec -n hello.exe 3
64位系统下的fotran程序编译与32位下类似,只是需要编译mpi模块和libmsmpi.a库时用的需要是x64目录下的文件,即:
编译生成mpi模块时,复制库目录下x64目录的mpifptr.h,即C:\Program Files (x86)\Microsoft SDKs\MPI\Include\x64\mpifptr.h
重新生成静态链接库时,复制64位库目录下的msmpi.dll,即C:\Windows\SysWOW64\msmpi.dll
编译fortran源代码并运行完全相同。
通过上述步骤,实现了windows32位和64位系统下,利用msmpi和mingw的gcc编译器构建mpi并行程序。对于c/c++程序只要注意头文件就可以直接编译运行。对于fortran程序则需要重新编译mpi模块和链接库,然后利用生成的模块和链接库进行编译。
注意上述测试的软件版本为msmpi8.1,mingw 6.3.0。还要注意因为64位环境和32位环境本身是隔离的,因此不需要像miroi那样在代码中加入区分64位和32位的预编译命令,编译也不需要使用_WIN64选项了。