介绍

MPI(Message Passing Interface)是上世纪90年代定义的一个接口标准,这个标准接口使得程序员写的并发程序可以在所有主流的并发框架中运行。

MPI 在消息传递模型设计上的一些经典概念,第一个是通讯器(communicator)通讯器定义了一组能够互相发消息的进程。在这组进程中,每个进程会被分配一个序号,称作(rank),进程间显性地通过指定秩来进行通信。

通信的基础建立在不同进程间发送和接收操作。一个进程可以通过指定另一个进程的秩以及一个独一无二的消息标签tag)来发送消息给另一个进程。接受者可以发送一个接收特定标签标记的消息的请求(或者也可以完全不管标签,接收任何消息),然后依次处理接收到的数据。类似这样的涉及一个发送者以及一个接受者的通信被称作点对点(point-to-point)通信。

当然在很多情况下,某个进程可能需要跟所有其他进程通信。比如主进程想发一个广播给所有的从进程。在这种情况下,手动去写一个个进程点对点的信息传递就显得很笨拙。而且事实上这样会导致网络利用率低下。MPI 有专门的接口来帮我们处理这类所有进程间的集合(collective)通信。

把点对点通信和集体性通信这两个机制合在一起已经可以创造十分复杂的并发程序了。

安装

mpi有多种不同的实现,这里使用mpich的实现

  • Linux从镜像源安装(推荐)
# Ubuntu
apt-get update && apt-get install mpich

# Centos
yum install mpich mpich-devel

# 安装完成后
mpiexec --version
./configure --disable-fortran --prefix=/usr/local/mpich
make; sudo make install

单机

安装完成后测试一下单机使用,编辑如下hello_world.c文件

#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {
    // Initialize the MPI environment
    MPI_Init(NULL, NULL);

    // Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

    // Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

    // Get the name of the processor
    char processor_name[MPI_MAX_PROCESSOR_NAME];
    int name_len;
    MPI_Get_processor_name(processor_name, &name_len);

    // Print off a hello world message
    printf("Hello world from processor %s, rank %d out of %d processors\n",
           processor_name, world_rank, world_size);

    // Finalize the MPI environment.
    MPI_Finalize();
}

使用mpicc编译,并使用mpirun执行

mpicc hello_world.c -o hello_world
# 使用mpiexec或mpirun启动执行
mpiexec -n 4 ./hello_world
# 输出如下
Hello world from processor VM38776, rank 1 out of 4 processors
Hello world from processor VM38776, rank 0 out of 4 processors
Hello world from processor VM38776, rank 3 out of 4 processors
Hello world from processor VM38776, rank 2 out of 4 processors

多机

多机执行,首先需要确保多个机器上安装同版本或者版本接近的mpi工具,并且机器之间可以互相无密码ssh访问。

配置免密访问

免密需要节点间建立互信,免密操作略。

下面操作可选,即配置/etc/hosts~/.ssh/config来便于地址解析和ssh连接,ssh参考配置如下

Host mpihost1
    HostName 91.200.139.182
    User root
    Port 10022
    StrictHostKeyChecking no

Host mpihost2
    HostName 91.200.139.183
    User root
    Port 10022
    StrictHostKeyChecking no

编辑mpi host配置

编辑如下host_file文件,并指定每个节点的进程数

mpihost1:3
mpihost2:1

含义是在mpihost1上启动3个进程,在mpihost2上启动1个进程

接着在两个节点分别编译hello_world.c文件,并将可执行文件放在/tmp/hello_world

# 启动4个进程
mpiexec -n 4 -f host_file /tmp/hello_world

# 输出如下
Hello world from processor mpihost1, rank 0 out of 4 processors
Hello world from processor mpihost1, rank 1 out of 4 processors
Hello world from processor mpihost1, rank 2 out of 4 processors
Hello world from processor mpihost2, rank 3 out of 4 processors

总结多机mpi运行要满足条件:

  • mpi安装版本和路径一致
  • 节点间可以免密ssh通信
  • mpiexec运行的可执行文件在不同节点的路径相同

参考

mpitutorial/mpitutorial: MPI programming lessons in C and executable code examples

MPI 教程介绍 · MPI Tutorial

MPI Hello World · MPI Tutorial