这篇文章上次修改于 1337 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

MPI 简介

(英语:Message Passing Interface,缩写MPI)是一个平行计算应用程序接口(API),常在超级电脑电脑丛集等非共享内存环境程序设计。

MPI 是一个跨语言的通信协议, 用于编写并行计算程序,主要希望解决的问题是高性能,大规模性,和可移植性。

MPI属于OSI参考模型的第五层或者更高,他的实现可能通过传输层的sockets和Transmission Control Protocol (TCP)覆盖大部分的层。

其他详细介绍可以参考wiki: MPI

MPI的简单使用

例一 MPI常用接口

通过一个简单的DEMO, 演示MPI的常用编程思想,以及使用流程。

#include "mpi.h"
#include <stdio.h>
#include <math.h>
void 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);
    fprintf(stderr,"Hello World! Process %d of %d on %s\n",myid, numprocs, processor_name);
    MPI_Finalize();
}

编译后在集群节点通过 mpirunmpiexec 执行。

# mpirun -np 4 -hostfile nodefile demo
Hello World! Process 0 of 4 on tp5
Hello World! Process 1 of 4 on tp1
Hello World! Process 2 of 4 on tp3
Hello World! Process 3 of 4 on tp4

上面执行的命令指定4个进程, 通过nodefile指定节点名字。分别在tp1,tp3,tp4,tp5四个节点上运行。

通过 mpirun 运行的程序,会分布到集群不同的节点上执行,每个节点上可以执行多个进程。进程间通过 MPI_Comm_rank 接口获取到的rank值进行区分。程序可以通过该值进行任务的分配。

mpich接口文档

mpi

MPI_Init(int *argc, char ***argv): 用于初始化创建MPI的全局变量或者内部变量,当前MPI_Init接收的两个参数暂未使用。
MPI_Comm_rank ( MPI_Comm comm, int *rank ): 从communicator中获取当前线程的rank值。
int MPI_Comm_size ( MPI_Comm comm, int *size ): 获取所有与Communicator关联的线程总数。
int MPI_Get_processor_name(char *name,int *resultlen): 获取进程所在节点的名字。

例二 常用任务分配方式

假设有任务0-99。 通过5个节点,每节点2进程处理这些任务。

此时程序可以将0-99的任务分配到10个进程当中。

进程0: 0,10,20,30,40,50...,90
进程1: 1,11,21,31,41,51...,91
....
进程9: 9,19,29,39,49...99

这种任务分配可以通过rank值进行,代码如下

int rank;
int numproces;
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
for(int i = rank;i < 100;i += numprocess) {
    process(i);
}