MPI简介
MPI
简介
在程序中,不同的进程需要相互的数据交换,特别是在科学计算中,需要大规模的计算与数据交换,集群可以很好解决单节点计算力不足的问题,但在集群中大规模的数据交换是很耗费时间的,因此需要一种在多节点的情况下能快速进行数据交流的标准,这就是MPI。
MPI是一组用于多节点数据通信的标准,而非一种语言或者接口。具体的使用方法需要依赖它的具体实现(mpich or openmpi等)。
mpi的目标是
- 实现较高的通信性能
- 好的程序移植性
- 强大的功能
编译与运行
mpi目前绑定的语言只有FORTRAN 和 C/C++。
c编译: mpicc -o mpiProgram mpiProgram.c
c++编译:mpicxx -o mpiProgram mpiProgram.cpp
FORTRAN编译:mpif77 -o mpiProgram mpiProgram.f
运行可使用mpirun或mpiexec:
mpirun/mpiexec -np 2 mpiProgram
概念
进程
通俗的说,进程就是运行的程序。一个程序可以含有多个进程,但一个进程不能同属于多个程序。进程拥有独立的运行环境(内存,寄存器,CPU执行时间等),是操作系统中独立存在的可执行的基本单位。每个进程所占有的资源都是独立的,不与其他的进程共享,不能访问其他进程内存空间,其他进程也无法访问该进程内存空间。但可以通过消息传递来进行通信。
进程组
指一个mpi程序中的所有(n个)进程的集合。该程序中所有进程编号从0到n-1,主要是为了标识不同的进程,可以通过进程的编号来索引该进程。不同进程组的进程的编号可以相同。
通信器(MPI_Comm)
可以理解围殴一组进程间可以通信的进程组,通信函数必须在通信器内调用。
消息
需要通信的数据。
mpi对象
mpi内存的数据结构,包括数据类型(MPI_DOUBLE),通信器(MPI_COMM)等
mpi数据类型
MPI_BYTE为一个字节,即8bit。MPI_PACKED为打包数据类型,可以将自定义数据类型打包传递。
mpi模型基本结构
#include<mpi.h>
void main(int argv,char* argv[])}
int rank,size;
MPI_Init(&argc,&argv); //初始化MPI环境
MPI_Comm_rank(MPI_COMM_WORLD,&rank); //获取进程组中进程编号rank
MPI_Comm_size(MPI_COMM_WORLD,&size); //获取进程组中进程数size
.....
//各种操作
.....
MPI_Finalize(); //退出MPI环境
}
program main
include 'mpif.h'
character * (MPI_MAX_PROCESSOR_NAME) processor_name
integer myid, numprocs, namelen, rc, ierr
call MPI_INIT( ierr )
call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )
call MPI_FINALIZE(ierr)
end
首先就是导入mpi的头文件<mpi.h>,使用MPI_INIT(int* argc_p,char*** argv_p)函数初始化mpi。而后就是获取进程组中的进程编号以及进程总数MPI_Comm_rank(MPI_Comm int*),MPI_Comm_size(MPI_Comm , int*)。 设置完成即可进行数据通信操作。最后使用MPI_Finalize()退出MPI环境。
mpi基本函数(c版)
int MPI_Init(int *argc,char ***argv)
*argc为指向main函数argc的指针,***argv为指向main函数**argv的指针。一般不使用时设置为NULL
int MPI_Initialized(int *flag)
检测mpi环境是否初始化,唯一可在,MPI_Init前使用的函数。
int MPI_Comm_rank(MPI_Comm comm,int *rank)
int MPI_Comm_size(MPI_Comm comm,int *size)
MPI_Comm是进程通信器类型,即同一个通信器MPI_Comm中的可以进行通信。一般设为MPI_COMM_WORLD,即该程序的所有进程,也可以自己单独设置不同的通信器。rank为int型数组,保存该通信器中进程的编号。size为int型指针,保存该通信器中进程的数量。
int MPI_Send(void *buf, int count, MPI_Datatype datatype,int dest, int tag,MPI_Comm comm)
为阻塞型发送函数,即等消息发送后才可返回执行下一句。buf为发送区缓存。count为发送的数据的大小。datatype为发送的数据类型。dest为发送的目标进程编号。tag为标志,该标志必须和接收函数的标志一致时才可被接收函数接收。comm通信器。
int MPI_Recv (void *buf, int count, MPI_Datatype datatype,int source, int tag, MPI_Comm comm,MPI_Status *status)
为阻塞型接收函数,即接收到消息后才可返回执行下一句。buf为接收区缓存,接收区缓存必需大于等于发送的数据。count为接收的数据大小。datatype为接收的数据类型。source为数据的发送源进程编号。tag为标志,该标志必须与发送函数的tag一致才会被接收。comm为通信器。status返回接收状态。
int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag,MPI_Comm comm, MPI_Request *request)
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request)
为对应的发送接收函数的非阻塞型函数,即当函数执行后立马返回执行下一行代码,而不需要等待数据正式发送或接收后才可返回。这经常会导致数据的混乱,因此使用非阻塞发送和接收时格外需要注意。
int MPI_Finalize(void)
退出MPI环境函数,每个进程都必须调用。调用后不可在使用MPI函数。若不执行该函数,则进程可能会挂起。执行该函数前确保非阻塞通信结束。
int MPI_Abort(MPI_Comm comm, int errorcode)
异常终止函数。在出现了致命错误而希望异常终止MPI程序时执行,MPI系统会设法终止comm通信器中所有进程, 输入整型参数errorcode,将被作为进程的退出码返回给系统
int MPI_Get_processor_name(char *name,int *resultlen)
获取处理器名称,在返回的name中存储所在处理器的名称,resultlen存放返回名字所占字节,应提供参数name不少于MPI_MAX_PRCESSOR_NAME个字节的存储空间
int MPI_Get_version(int *version,int *subversion)
获取mpi版本号,若版本为4.0,则version为4,subversion为0.
double MPI_Wtime(void)
返回调用时刻的墙上时间,用浮点数表示秒数
- 点赞
- 收藏
- 关注作者
评论(0)