mpi具体实现之mpich的基本命令

本篇博客只是介绍mpich命令的使用,并没有涉及并行的底层原理,对应的版本为mpich-3.3.2,但相关命令对其他版本也适用


前言

MPI(Message Passing Interface)是一个消息传递接口的标准,是目前最重要的一个基于消息传递的并行编程工具,有多种不同的免费、高效、实用的实现版本,如openmpimpichlamchimp等。MPI以语言独立的形式来定义接口库,并实现了与C、C++、Fortan的绑定。


一、查看mpich版本及配置

mpichversion:查看mpich的版本及其配置。使用如下
mpichversion

二、编译和链接

使用mpich自带的脚本进行编译和链接,即mpiccmpicxxmpifort,分别对应使用C、C++、Fortran进行编写的程序。
例如,假设有一个C++程序cpi.cpp,则可以使用mpicxx进行编译的示例如下:

mpicxx -o cpi cpi.cpp

下面主要介绍mpicxx的命令行参数:

三、运行并行程序

MPI标准建议使用mpiexec运行MPI程序,MPICH实现了mpiexec标准并且对其进行了扩展。运行mpiexec前一定要先使用mpiccmpicxxmpifort生成可执行程序。

  • 在本地机器上运行具有number个进程的程序:
mpiexec -n <number> ./a.out
  • 在多个节点上运行number个进程的程序:
mpiexec -f machinefile -n <number> ./a.out 

四、6个基本mpi函数

  • int MPI_Init(int *argc, char ***argv)
    MPI程序通过调用MPI_Init函数进入MPI环境,并完成所有的初始化工作。
  • int MPI_Finalize(void)
    MPI程序通过调用MPI_Finalize函数从MPI环境中退出。
  • int MPI_Comm_rank(MPI_Comm comm, int *rank)
    MPI程序通过调用MPI_Comm_rank函数获取当前进程在指定的通信域中的编号,该编号可以将自身和其他进程区分开来,从而实现不同进程之间的并行与合作。
  • int MPI_Comm_size(MPI_Comm comm, int *size)
    MPI程序通过调用MPI_Comm_size函数获取指定通信域的进程的个数,进程可根据进程数来确定自己应该完成的任务比例。
  • int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
    该函数将起始地址为bufcountdatatype类型的数据发送给目标进程,目标进程在通信域comm中的编号由dest标识,同时发送方在发送该消息时给定的标签tag用于把本次发送的消息和本进程发送给同一目标进程的其他消息区分出来。
  • int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
    该函数从源进程接收一个消息,并且该消息的标签应该和参数tag一致,源进程在通信域中的编号由source标识。消息接收后存放在起始地址为buf的接收缓冲区,该缓冲区由countdatatype类型的连续数据元素组成。接收到的消息长度必须小于或等于接收内存区域的长度,因为如果接收到的消息过大,MPI并不截断,从而导致缓冲区溢出。

五、 一个简单的MPI程序(C++实现)

// 文件名 ex.cpp (可以随便取,下面运行时对应好即可)
#include <iostream>
#include <mpi.h>

int main(int arg, char **argv)
{
    int rank, size, tag = 1;
    int senddata, recvdata;
    MPI_Status status;
    MPI_Init(&arg, &argv); //MPI初始化
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); // 该进程在MPI_COMM_WORLD通信域中的编号
    MPI_Comm_size(MPI_COMM_WORLD, &size); // 通信域MPI_COMM_WORLD中总的进程数目
    
    if (rank == 0)
    {
        senddata = 9999;
        MPI_Send(&senddata, 1, MPI_INT, 1, tag, MPI_COMM_WORLD);  //进程0发送数据到进程1
    }
    else if(rank == 1)
    {
        MPI_Recv(&recvdata, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &status);  //进程0接收进程0发送的数据
        std::cout << recvdata << std::endl;
        std::cout << "数据发送方:" << status.MPI_SOURCE << "\n消息的标签:" << status.MPI_TAG << "\n接收操作的错误代码" << status.MPI_ERROR << std::endl; 
     }
     MPI_Finalize();  //MPI结束函数
     return 0;
}

程序说明:

  1. mpi.h头文件包含MPI函数和数据类型的定义。
  2. 该程序包括使进程0向进程1发送一个整数类型的数据,进程1接收该数据并打印。
  3. MPI_COMM_WORLD是MPI标准预定义的通信域,所有的MPI进程都属于该通信域。
  4. MPI_Status是MPI中定义的类型数据,分别有三个域,可以通过status.MPI_SOURCE,status.MPI_TAG和status.MPI_ERROR的方式调用这三个信息,其中status已经定义为MPI_Status变量。这三个信息分别返回的值是所收到数据发送源的进程号,该消息的tag值和接收操作的错误代码。
  5. 运行该程序方式如下(以Linux终端为例),进程数可以指定为大于等于2的任一整数:
mpicxx -o ex ex.cpp
mpiexec -n 2 ./ex
mpiexec -n 5 ./ex

总结

本文仅仅简单介绍了mpich的使用,安装部分可以自行解决(后面有空也可以写写)。此外还介绍了MPI标准的6个基本函数,这在所有MPI的具体实现上都是一致的,如openmpi。最后一个简单的MPI程序介绍了6个基本函数的使用。


参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值