for (i=0;i<50;i++)
MPI_Pack(A+i*j,1,MPI_DOUBLE,TempBuffer,
Buffersize,&Position,comm);
MPI_Send(TempBuffer,Position,MPI_PACKED,dest,..);
消息信封表示一个接收者的信息,MPI 中由 3 部分组成:destination、tag 和 communicator。
消息标志 tag: 整数,标识不同类型消息并限定消息接收。设置原因:
●避免消息后发先至,造成接收错误;
●服务进程通过判定消息标志,可完成相应处理。
消息状态 status (MPI_Status 类型)存放接收消息的状态信息,包括消息的源进程标识、消息标签、
包含的数据项个数等。
它是消息接收函数 MPI_Recv 的最后一个参数
当一个接收者从不同进程接收不同大小和不同标签的消息时,消息的状态信息非常有用。
一个进程组可以有多个通信子;不同通信子可包含不同进程。
求π:
#define N 1000000
Main() { double local, pi,w;
long i,taskid,numtask;
w=1.0/N;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
MPI_Comm_size(MPI_COMM_WORLD,&numtask);
forall (i=taskid; i
群集通信:
广播:MPI_Bcast(Address, Count, Datatype, Root, Comm) 如:MPI_Bcast( &value, 1, MPI_INT, 0,
MPI_COMM_WORLD );
Broadcast 的特点
标号为 Root 的进程发送相同的消息给通信域 Comm 中的所有进程。
消息的内容如同点对点通信一样由三元组
标识。
对 Root 进程来说,这个三元组既定义了发送缓冲也定义了接收缓冲。对其它进程来
说,这个三元组只定义了接收缓冲
收集:MPI_Gather(SendAddress, SendCount, SendDatatype,RecvAddress, RecvCount, RecvDatatype,
Root, Comm)
Gather 的特点
在收集操作中,Root 进程从进程域 Comm 的所有进程(包括它自已)接收消息。
这 n 个消息按照进程的标识 rank 排序进行拼接,然后存放在 Root 进程的接收缓冲
中。
接收缓冲由三元组标识,发送缓冲由三元组
标识,所有非 Root 进程忽略接收缓冲。
如:rbuf=(int *)malloc(gsize*100*sizeof(int));
MPI_Gather(sendarray, 100, MPI_INT, rbuf, 100, MPI_INT, root, comm);
散播:MPI_Scatter(SendAddress, SendCount, SendDatatype,RecvAddress, RecvCount, RecvDatatype,
Root, Comm) 如 MPI_Scatter(sendbuf, 100, MPI_INT, rbuf, 100, MPI_INT, root, comm);
Scatter 的特点
Scatter 执行与 Gather 相反的操作。
Root 进程给所有进程(包括它自已)发送一个不同的消息,这 n (n 为进程域 comm 包
括的进程个数)个消息在 Root 进程的发送缓冲区中按进程标识的顺序有序地存放。
每个接收缓冲由三元组标识,所有的非
Root 进程忽略发送缓冲。对 Root 进程,发送缓冲由三元组标识。
全 局 收 集 : MPI_Allgather(SendAddress, SendCount, SendDatatype, RecvAddress, RecvCount,
RecvDatatype, Comm)
Allgather 操作相当于每个进程都作为 ROOT 进程执行了一次 Gather 调用,即每一个进程都按照
Gather 的方式收集来自所有进程(包括自己)的数据。
全局交换:MPI_Alltoall(SendAddress, SendCount, SendDatatype, RecvAddress,RecvCount,
RecvDatatype, Comm)
Alltoall 的特点
在全局交换中,每个进程发送一个消息给所有进程(包括它自已)。
这 n (n 为进程域 comm 包括的进程个数)个消息在它的发送缓冲中以进程标识的顺序
有序地存放。从另一个角度来看这个通信,每个进程都从所有进程接收一个消息,
这 n 个消息以标号的顺序被连接起来,存放在接收缓冲中。
全局交换等价于每个进程作为 Root 进程执行了一次散播操作。
路障同步的调用格式如下:
MPI_Barrier(Comm)
在路障同步操作 MPI_Barrier(Comm)中,通信域 Comm 中的所有进程相互同步。
在该操作调用返回后,可以保证组内所有的进程都已经执行完了调用之前的所有操
作,可以开始该调用后的操作。
群集通信的聚集:
归约:MPI_Reduce(SendAddress, RecvAddress, Count, Datatype, Op, Root, Comm)
Reduce 的特点
归约操作对每个进程的发送缓冲区(SendAddress)中的数据按给定的操作进行
运算,并将最终结果存放在 Root 进程的接收缓冲区(RecvAddress)中。
参与计算操作的数据项的数据类型在 Datatype 域中定义,归约操作由 Op 域
定义。
归约操作可以是 MPI 预定义的,也可以是用户自定义的。
归约操作允许每个进程贡献向量值,而不只是标量值,向量的长度由 Count
定义。
扫描:MPI_scan(SendAddress, RecvAddress, Count, Datatype, Op, Comm)
scan 的特点
可以把扫描操作看作是一种特殊的归约,即每一个进程都对排在它前面的进
程进行归约操作。
MPI_SCAN 调用的结果是,对于每一个进程 i,它对进程 0,1,…,i 的发送缓冲
区的数据进行了指定的归约操作。
扫描操作也允许每个进程贡献向量值,而不只是标量值。向量的长度由 Count
定义。
求π:
#include "mpi.h"
#include
#include
double f(double a)
{
return (4.0 / (1.0 + a*a));
}
void main(int argc, char *argv[])
{
namelen;
int done = 0, n, myid, numprocs, i;
double PI25DT = 3.141592653589793238462643;
double mypi, pi, h, sum, x;
double startwtime, endwtime;
int
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Get_processor_name(processor_name,&namelen);
fprintf(stderr,"Process %d on %s\n", myid, processor_name);
fflush(stderr);
n = 0;
while (!done)
{
if (myid == 0)