MPI知识点总结
MPI知识点总结
- 点对点
- 阻塞式通信
- MPI_Send
- MPI_Recv
- 非阻塞式通信
- MPI_ISend
- MPI_IRecv
- MPI_Wait
- 阻塞式通信
- 同步聚合
- 栅栏同步
- MPI_Barrier
- 栅栏同步
- 通信聚合
- 广播
- MPI_Bcast
- 分散
- MPI_Scatter
- 收集
- MPI_Gather
- 全部收集
- MPI_Allgather
- 广播
- 规约聚合
- 规约操作
- MPI_Reduce
- MPI_Allreduce
- 规约操作
几个重要函数
MPI_Scatter
MPI_Scatter与MPI_Bcast非常相似,都是一对多的通信方式,不同的是后者的0号进程将相同的信息发送给所有的进程,而前者则是将一段array 的不同部分发送给所有的进程,其区别可以用下图概括:
MPI_Scatter(
void* send_data,//存储在0号进程的数据,array
int send_count,//具体需要给每个进程发送的数据的个数
//如果send_count为1,那么每个进程接收1个数据;如果为2,那么每个进程接收2个数据
MPI_Datatype send_datatype,//发送数据的类型
void* recv_data,//接收缓存,缓存 recv_count个数据
int recv_count,
MPI_Datatype recv_datatype,
int root,//root进程的编号
MPI_Comm communicator)
MPI_Gather
MPI_Gather和MPI_scatter刚好相反,他的作用是从所有的进程中将每个进程的数据集中到根进程中,同样根据进程的编号对array元素排序,如图所示:
MPI_Gather(
void* send_data,
int send_count,
MPI_Datatype send_datatype,
void* recv_data,
int recv_count,//注意该参数表示的是从单个进程接收的数据个数,不是总数
MPI_Datatype recv_datatype,
int root,
MPI_Comm communicator)
MPI_Allgather
当数据分布在所有的进程中时,MPI_Allgather将所有的数据聚合到每个进程中。
MPI_Allgather(
void* send_data,
int send_count,
MPI_Datatype send_datatype,
void* recv_data,
int recv_count,
MPI_Datatype recv_datatype,
MPI_Comm communicator)
MPI_Allgatherv
/*
* 收集所有任务的数据并将组合数据传送到所有任务
* int MPI_Allgatherv(const void * sendbuf,int sendcount,MPI_Datatype sendtype,
* void * recvbuf,const int * recvcounts,const int * displs,
* MPI_Datatype recvtype,MPI_Comm comm)
*
* sendbuf:要发送内容的起始地址
* sendcount:要发送的数量
* sendtype:要发送数据的类型
* recvbuf:接收数据要存放的单元的地址
* recvcounts:这是一个整数数组,包含从每个进程要接收的数据量,比如{0, 1} 从0号进程接收0个,从1号进程接收1个
* displs:这是一个整数数组,包含存放从每个进程接收的数据相对于recvbuf的偏移地址
* recvtype:要接收的数据类型
* comm:通信集合
*/
MPI_Allagtherv解决MPI_Allagther要求每个进程处理任务量必须均等的问题,通过recvcounts数组指定每个进程接收任务的数量,通过displs数组指定每个进程发送的数据在接收缓冲区中的偏移量。
MPI_Alltoall
int MPI_Alltoall(const void *sendbuf, //发送缓冲区的起始地址
int sendcount, //要发送的数量
MPI_Datatype sendtype, //发送的数据类型
void *recvbuf, //接收缓冲区的起始位置
int recvcount, //要接收的数量
MPI_Datatype recvtype, //要接收的类型
MPI_Comm comm) //通信子
函数原理示意图如下,分别演示了发送缓冲区数据量为1和2时的发送和接收情况:
MPI_Alltoallv
有时候,我们当前进程往其他进程发送的数据不一样,个数也不一样,这个时候就需要用MPI_Alltoallv来解决。该函数用法类似于MPI_Allgather和MPI_Allgatherv的区别,即发送缓冲区的大小可以不相同(通过数组指定大小)。
int MPI_Alltoallv(const void *sendbuf,
const int *sendcounts,
const int *sdispls,
MPI_Datatype sendtype,
void *recvbuf,
const int *recvcounts,
const int *rdispls,
MPI_Datatype recvtype,
MPI_Comm comm)
相比MPI_Alltoall,这个方法有几个参数不一样:
int* sendcounts 和int *recvcounts。这两个参数你可以把它当做两个数组,数组中的元素代表往其他节点各发送(接收)多少数据。比如说,sendcounts[0]=3,sendcounts[1]=4,代表该节点要往0号节点发送3个sendtype的数据,往1号节点发送4个sendtype的数据。
多了两个参数,int *sdispls和int *rdispls,这两个可以看做是数组,数组中的每个元素代表了要发送(接收)的那块数据相对于缓冲区起始位置的位移量。
MPI_Reduce
归约聚合类似于收集,但对收集的数据执行某种归约操作,例如计算总和,查找最大值或执行某些用户定义的操作。
规约函数 MPI_Reduce(),将通信子内各进程的同一个变量参与规约计算,并向指定的进程输出计算结果。
MPI_METHOD MPI_Reduce(
_In_range_(!= , recvbuf) _In_opt_ const void* sendbuf, // 指向输入数据的指针
_When_(root != MPI_PROC_NULL, _Out_opt_) void* recvbuf, // 指向输出数据的指针,即计算结果存放的地方
_In_range_(>= , 0) int count, // 数据尺寸,可以进行多个标量或多个向量的规约
_In_ MPI_Datatype datatype, // 数据类型
_In_ MPI_Op op, // 规约操作类型
_mpi_coll_rank_(root) int root, // 目标进程号,存放计算结果的进程
_In_ MPI_Comm comm // 通信子
);
demo:
{
int size, rank, data, dataCollect;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
data = rank;// 参与计算的数据
MPI_Reduce((void *)&data, (void *)&dataCollect, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);// 所有的进程都要调用,而不是只在目标进程中调用
MPI_Finalize();
}
MPI_Allreduce
规约并广播函数 MPI_Allreduce(),在计算规约的基础上,将计算结果分发到每一个进程中,相比于 MPI_Reduce(),只是少了一个 root 参数。除了简单的先规约再广播的方法,书中介绍了蝶形结构全局求和的方法。
少了一个root参数是因为该函数将计算的结果广播到每个进程中去,各个进程均更新数据。
_Pre_satisfies_(recvbuf != MPI_IN_PLACE) MPI_METHOD MPI_Allreduce(
_In_range_(!= , recvbuf) _In_opt_ const void* sendbuf,
_Out_opt_ void* recvbuf,
_In_range_(>= , 0) int count,
_In_ MPI_Datatype datatype,
_In_ MPI_Op op,
_In_ MPI_Comm comm
);
demo:
{
int size, rank, data, dataCollect;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
data = rank;
MPI_Reduce((void *)&data, (void *)&dataCollect, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);// 所有的进程都要调用
MPI_Finalize();
}
上一篇: 【进程通讯】java 进程通讯
下一篇: RUNOOB python练习题29
推荐阅读
-
MPI知识点总结
-
Mybatis框架总结(二)
-
Spring Boot 总结
-
mangos 的执行模型 博客分类: c++技术随笔游戏总结整理 gsmangosrun
-
网游服务端技术总结 基于mangos源码 (一) 博客分类: 游戏c++ gameservermangos多线程
-
Spring-AOP 混合使用各种切面类型及不同切面总结
-
AOP使用总结
-
成功页面返回到固定某页面 博客分类: 2006年以前项目总结 StrutsJSPXML
-
项目经验~~ 博客分类: 2006年以前项目总结 log4jBeanOracleSQL
-
首页面下拉框内容状态的保持 博客分类: 2006年以前项目总结 JSPXML