一、openMp与MPI区别
有一个很大的区别: mpi 是基于消息传递的,适合多机系统,而 openmp 是基于内存共享的,适合单机多核、共享内存的系统。
所谓MPI复杂是指需要程序员手动管理数据是怎么partition的,并且要手动实现进程之间的相互通信(例如MPI_Send, MPI_Recv),以及维持同步(scynchronization, 例如MPI_Barrier),但这一切都是尽在程序员掌握之中的。
OpenMP和MPI是并行编程的两个手段,对比如下:
OpenMP:线程级(并行粒度);共享存储;隐式(数据分配方式);可扩展性差;
MPI:进程级;分布式存储;显式;可扩展性好。
OpenMP采用共享存储,意味着它只适应于SMP,DSM机器,不适合于集群。MPI虽适合于各种机器,但它的编程模型复杂:
需要分析及划分应用程序问题,并将问题映射到分布式进程集合;
需要解决通信延迟大和负载不平衡两个主要问题;
调试MPI程序麻烦;
MPI程序可靠性差,一个进程出问题,整个程序将错误。
二、MPI常用语法API
MPI只是提供一种粗粒度的并行机制,而在进程粒度上,MPI程序仍是串行执行。
MPI点到点通信包括:阻塞通信(标准通信模式<简单、常用>、缓冲通信模式、就绪通信模式、同步通信模式)、非阻塞通信(同样的4种模式)
主要包含以下几部分:
#include "mpi.h“
MPI_Init( &argc, &argv );
MPI_Finalize();
编译运行命令:
mpicc -o hello hello.c
mpirun -np 4 ./hello
写MPI程序时,首要考虑:
任务由多少个进程来进行并行计算? 我是哪一个进程?
int MPI_Comm_size(MPI_Comm comm, int *size); 获得进程个数 p
int MPI_Comm_rank(MPI_Comm comm, int *rank); 获得进程的一个叫rank的值,该rank值为0到p-1间的整数,相当于进程的ID
消息传送 (数据传送 + 同步操作)
MPI_Send(void *message, 被传送数据的起始地址
int count, 被传送的数据项的个数
MPI_Datatype datatype,数据项的类型
int dest, 接收消息的进程号
int tag, 此消息的一个标记,可以用来说明消息的不同用途
MPI_Comm comm 此消息所在的通信域
);
MPI_Recv(B, 20, MPI_DOBULE, 0, 99, MPI_COMM_WORLD, &status);
参数解释
int MPI_Recv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status);
OUT buf 接收数据要被存放的空间的起始地址
IN count 接收进程所能够接收的最大数据项数
IN datatype 数据项的类型
IN source 发送消息的进程号
IN tag 对此消息所预期的标记值
IN comm 此消息所在的通信域
OUT status status对象,包含实际接收到的消息的有关信息(在调用MPI_Recv之前,需要分配一条类型为MPI_Status的记录,这是唯一的用户可访问的MPI的数据结构,参数status就是指向这条记录的指针)
MPI消息
数据:<起始地址、数据个数、数据类型>
信封:<源/目的、标识、通信域>
Status还可用于返回实际接收到消息的长度
int MPI_Get_count(MPI_Status status, MPI_Datatype datatype,int* count)
IN status 接收操作的返回值.
IN datatype 接收缓冲区中元素的数据类型.
OUT count 接收消息中的元素个数.
发送和接收是成对出现的,忽略这个原则 很可能会产生死锁
int MPI_Sendrecv(
void *sendbuf,
int sendcount,
MPI_Datatype sendtype,
int dest,
int sendtag,
void *recvbuf,
int recvcount,
MPI_Datatype recvtype,
int source,
int recvtag,
MPI_Comm comm,MPI_Status *status)
MPI_Sendrecv( &a, 1, MPI_INT, dest, 99, &b 1, MPI_INT, source, 99, MPI_COMM_WORLD, &status);