windows下利用Mingw和msmpi编译运行mpi并行程序

windows下利用Mingw和msmpi编译运行mpi并行程序

目前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

mingw的gcc编译系统是一整套的编译器,包含gcc,g++,gfortran等分别编译c,c++,fortran程序。

下载一套mingw,地址:mingw。不用安装,直接解压到某个位置,把mingw下的bin目录加入环境变量。

msmpi

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代码如下:

hello.c

#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();
}

hello.cpp

#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"<

hello.f90

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

windows环境

测试环境包括32位和64位windows7系统,可以直接安装在电脑上或者在虚拟机中。

32位windows 7系统的c/c++语言mpi并行程序

在安装完成软件并准备好程序代码之后,我们开始进行测试,注意到一般情况下,c和c++的mpi程序代码中会仅包含mpi.h头文件用于处理MPI函数。如果是这样的话,直接进行编译,那么会提示错误:

error: '__int64'
does not name a type; did you mean '__divtc3'?
typedef __int64 MPI_Aint;

这是因为__int64未定义,这个问题有两种方法解决:

  1. 是修改mpi.h文件找到__int64定义语句前面,加入#include “stdint.h”
  2. 是不修改mpi.h文件,而如上面的程序代码一般,直接在源代码中mpi.h前面加入stdint.h

解决了这个问题以后,那么就可以正常的进行编译和运行了。

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

32位windows 7系统的fotran语言mpi并行程序

fortran程序的编译要复杂很多,根据miroi的研究表明,不能直接进行编译,源代码中包含的文件也不是mpif.h,而需要使用mpi模块,该模块需要手动编译。并且因此,需要利用dlltool工具重新生成一个静态链接库,而不是使用原来的msmpi.lib。步骤如下:

  1. 编译生成mpi模块

复制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模块即可。

  1. 重新生成静态链接库

复制系统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文件。

  1. 编译fortran源代码并运行

现在所有的准备都已经完成,利用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位windows 7系统的c/c++语言mpi并行程序

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位windows 7系统的fotran语言mpi并行程序

64位系统下的fotran程序编译与32位下类似,只是需要编译mpi模块和libmsmpi.a库时用的需要是x64目录下的文件,即:

  1. 编译生成mpi模块时,复制库目录下x64目录的mpifptr.h,即C:\Program Files (x86)\Microsoft SDKs\MPI\Include\x64\mpifptr.h

  2. 重新生成静态链接库时,复制64位库目录下的msmpi.dll,即C:\Windows\SysWOW64\msmpi.dll

  3. 编译fortran源代码并运行完全相同。

小结

通过上述步骤,实现了windows32位和64位系统下,利用msmpi和mingw的gcc编译器构建mpi并行程序。对于c/c++程序只要注意头文件就可以直接编译运行。对于fortran程序则需要重新编译mpi模块和链接库,然后利用生成的模块和链接库进行编译。

ps

注意上述测试的软件版本为msmpi8.1,mingw 6.3.0。还要注意因为64位环境和32位环境本身是隔离的,因此不需要像miroi那样在代码中加入区分64位和32位的预编译命令,编译也不需要使用_WIN64选项了。

参考文献

  1. TUTORIAL: Adapting MS-MPI for MinGW64 #85
  2. Linking MS-MPI with MinGW (gfortran)
  3. MinGW coding under Windows (C, C++, OpenMP, MPI)
  4. How to Configure MSMPI for the MinGW-w64 Cross-Compiler
  5. Microsoft MPI
  6. How to compile and run a simple MS-MPI program
  7. MPI在windows上的扯淡

你可能感兴趣的:(科学计算)