MPI聚合函数
MPI聚合通信
- MPI_Barrier
int MPI_Barrier(
MPI_Comm comm
);
所有在该通道的函数都执行完后,才开始其他步骤。
0进程在状态T1调用MPI_Barrier
函数,并在该位置挂起,等待其他进程到达。最后在T4状态同时进行。
例子:
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<time.h>
int main(int argc, char* argv[])
{
int rank, nprocs;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Barrier(MPI_COMM_WORLD);
printf("Hello,world,I am %d of %d\n", rank, nprocs);
MPI_Finalize();
return 0;
}
- MPI_Bcast
int MPI_Bcast(
void *buffer,
int count,
MPI_Datatype datatype,
int root,
MPI_Comm comm
);
广播函数,root表示要广播的进程。发送和接收进程都需要写该函数。
例子:
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<time.h>
int main(int argc, char* argv[])
{
int rank,nproc;
int ibuf;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) ibuf = 8888;
else ibuf = 0;
MPI_Bcast(&ibuf, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (rank != 0)
{
printf("rank = %d ibuf = %d\n", rank, ibuf);
}
MPI_Finalize();
return 0;
}
- MPI_Gather
int MPI_Gather(
void *sendbuf,
int sendcnt,
MPI_Datatype sendtype,
void *recvbuf,
int recvcnt,
MPI_Datatype recvtype,
int root,
MPI_Comm comm
);
每个进程(包括root进程)都要发送buffer给root进程,root进程接收到这些buffer并且按照顺序排好序。
例子:
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<time.h>
int main(int argc, char* argv[])
{
int rank, nproc;
int isend, irecv[32];
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
isend = rank + 1;
MPI_Gather(&isend, 1, MPI_INT, irecv, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (rank == 0)
{
for (int i = 0; i < nproc; i++)
{
printf("%d \n", irecv[i]);
}
}
MPI_Finalize();
return 0;
}
- MPI_Gatherv
int MPI_Gatherv(
void *sendbuf,
int sendcnt,
MPI_Datatype sendtype,
void *recvbuf,
int *recvcnts,
int *displs,// 接收的数据放在说明位置,即位移。
MPI_Datatype recvtype,
int root,
MPI_Comm comm
);
是MPI_Gather函数的一个扩展,recvcnts是数组,允许每个进程的数量不同,而且每个进程的位置更灵活。
例子:
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<time.h>
int main(int argc, char* argv[])
{
//这里为了简单,假设有4个进程。
int send_buffer[6];
int recv_buffer[6];
int rank, nproc;
int receive_counts[4] = { 0,1,2,3 };
int receive_disp[4] = { 0,0,1,3 };//偏移数组
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
//初始化数据
for (int i = 0; i < rank; i++)
{
send_buffer[i] = rank;
recv_buffer[i] = rank+1;
}
MPI_Gatherv(send_buffer, rank, MPI_INT, recv_buffer, receive_counts, receive_disp, MPI_INT, 0, MPI_COMM_WORLD);
if (rank == 0)
{
for (int i = 0; i < 6; i++)
{
printf("[%d]", recv_buffer[i]);
}
}
MPI_Finalize();
return 0;
}
- MPI_Scatter
int MPI_Scatter(
void *sendbuf,
int sendcnt,
MPI_Datatype sendtype,
void *recvbuf,
int recvcnt,
MPI_Datatype recvtype,
int root,
MPI_Comm comm
);
MPI_Scatter与MPI_Bcast非常相似,都是一对多的通信方式,不同的是后者的0号进程将相同的信息发送给所有的进程,而前者则是将一段array 的不同部分发送给所有的进程。
例子:
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<time.h>
#define MAX_PRO 10//最大进程数
int main(int argc, char* argv[])
{
int rank, nproc;
int table[MAX_PRO][MAX_PRO];
int row[MAX_PRO];
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0)
{
for (int i = 0; i < nproc; i++)
{
for (int j = 0; j < MAX_PRO; j++)
{
table[i][j] = i + j;
}
}
}
MPI_Scatter(&table[0][0], MAX_PRO, MPI_INT, &row[0], MAX_PRO, MPI_INT, 0, MPI_COMM_WORLD);
if (rank != 0)
{
for (int i = 0; i < MAX_PRO; i++)
{
printf("%d ", row[i]);
}
printf("processs of %d\n",rank);
}
MPI_Finalize();
return 0;
}
- MPI_Alltoall
int MPI_Alltoall(
void *sendbuf,
int sendcount,
MPI_Datatype sendtype,
void *recvbuf,
int recvcount,
MPI_Datatype recvtype,
MPI_Comm comm
);
当前进程向其他每个进程(包括自己)要发送数据,都是发送sendbuf中的数据。接收到不同进程的数据。
例子:
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<time.h>
int main(int argc, char* argv[])
{
int rank, nproc;
int send[1];
int recv[10];
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
send[0] = rank*rank;
for (int i = 0; i < 10; i++)
{
recv[i] = 0;
}
MPI_Alltoall(&send, 1, MPI_INT, recv, 1, MPI_INT, MPI_COMM_WORLD);
if (rank == 0)
{
for (int i = 0; i < 10; i++)
{
printf("%d ", recv[i]);
}
}
MPI_Finalize();
return 0;
}
MPI归约操作
- MPI_Reduce
int MPI_Reduce(
void *sendbuf,
void *recvbuf,
int count,
MPI_Datatype datatype,
MPI_Op op,
int root,
MPI_Comm comm
);
MPI_Op有如下类型:
运算操作符 | 描述 | 运算操作符 | 描述 |
---|---|---|---|
MPI_MAX | 最大值 | MPI_LOR | 逻辑或 |
MPI_MIN | 最小值 | MPI_BOR | 位与 |
MPI_SUM | 求和 | MPI_LXOR | 逻辑异或 |
MPI_PROD | 求积 | MPI_BXOP | 位异或 |
MPI_LAND | 逻辑与 | MPI_MINLOC | 计算一个全局最小值 |
MPI_BAND | 位与 | MPI_MAXLOC | 计算一个全局最大值 |
将通信子内各进程的同一个变量参与规约计算,并向指定的进程输出计算结果。
例子:
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<time.h>
int main(int argc, char* argv[])
{
int rank, nproc;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int send = rank;
int recv;
MPI_Reduce(&send, &recv, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0)
{
printf("%d", recv);
}
MPI_Finalize();
return 0;
}
- MPI_Scan
int MPI_Scan(
void *sendbuf,
void *recvbuf,
int count,
MPI_Datatype datatype,
MPI_Op op,
MPI_Comm comm
);
前缀和函数 MPI_Scan(),将通信子内各进程的同一个变量参与前缀规约计算,并将得到的结果发送回每个进程,使用与函数 MPI_Reduce() 相同的操作类型。
例子:
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<time.h>
int main(int argc, char* argv[])
{
int rank, nproc;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int send = rank;
int recv;
MPI_Scan(&send, &recv, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
printf("the %d process is %d", rank, recv);
MPI_Finalize();
return 0;
}
- MPI_Reduce_scatter
int MPI_Reduce_scatter(
void *sendbuf,
void *recvbuf,
int *recvcnts,
MPI_Datatype datatype,
MPI_Op op,
MPI_Comm comm
);
将规约结果分片发送到各进程.
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<time.h>
int main(int argc, char** argv)
{
int* sendbuf, recvbuf, * recvcounts;
int size, rank;
MPI_Comm comm;
MPI_Init(&argc, &argv);
comm = MPI_COMM_WORLD;
MPI_Comm_size(comm, &size);
MPI_Comm_rank(comm, &rank);
sendbuf = (int*)malloc(size * sizeof(int));
for (int i = 0; i < size; i++)
sendbuf[i] = i;
recvcounts = (int*)malloc(size * sizeof(int));
for (int i = 0; i < size; i++)
recvcounts[i] = 1;
MPI_Reduce_scatter(sendbuf, &recvbuf, recvcounts, MPI_INT, MPI_SUM, comm);
printf("the %d process is %d", rank, recvbuf);
MPI_Finalize();
return 0;
}
MPI聚合函数的更多相关文章
- 可以这样去理解group by和聚合函数
写在前面的话:用了好久group by,今天早上一觉醒来,突然感觉group by好陌生,总有个筋别不过来,为什么不能够select * from Table group by id,为什么一定不能是 ...
- TSQL 聚合函数忽略NULL值
max,min,sum,avg聚合函数会忽略null值,但不代表聚合函数不返回null值,如果表为空表,或聚合列都是null,则返回null.count 聚合函数忽略null值,如果聚合列都是null ...
- SQL Server 聚合函数算法优化技巧
Sql server聚合函数在实际工作中应对各种需求使用的还是很广泛的,对于聚合函数的优化自然也就成为了一个重点,一个程序优化的好不好直接决定了这个程序的声明周期.Sql server聚合函数对一组值 ...
- Mongodb学习笔记四(Mongodb聚合函数)
第四章 Mongodb聚合函数 插入 测试数据 ;j<;j++){ for(var i=1;i<3;i++){ var person={ Name:"jack"+i, ...
- sql语句 之聚合函数
聚合分析 在访问数据库时,经常需要对表中的某列数据进行统计分析,如求其最大值.最小值.平均值等.所有这些针对表中一列或者多列数据的分析就称为聚合分析. 在SQL中,可以使用聚合函数快速实现数据的聚 ...
- oracle数据库函数之============‘’分析函数和聚合函数‘’
1分析函数 分析函数根据一组行来进行聚合计算,用于计算完成狙击的累积排名等,分析函数为每组记录返回多个行 rank_number() 查询结果按照次序排列,不存在并列和站位的情况,可以用于做Oracl ...
- ORACLE 自定义聚合函数
用户可以自定义聚合函数 ODCIAggregate,定义了四个聚集函数:初始化.迭代.合并和终止. Initialization is accomplished by the ODCIAggrega ...
- sql 聚合函数、排序方法详解
聚合函数 count,max,min,avg,sum... select count (*) from T_Employee select Max(FSalary) from T_Employee 排 ...
- SQL Server 自定义聚合函数
说明:本文依据网络转载整理而成,因为时间关系,其中原理暂时并未深入研究,只是整理备份留个记录而已. 目标:在SQL Server中自定义聚合函数,在Group BY语句中 ,不是单纯的SUM和MAX等 ...
随机推荐
- Django学习路26_转换字符串大小写 upper,lower
在 urls 中注册 url(r'getstr',views.getstr) 在 views.py 中添加函数 def getstr(request): string = 'abc' string_2 ...
- KNN算法基本原理与sklearn实现
''' KNN 近邻算法,有监督学习算法 用于分类和回归 思路: 1.在样本空间中查找 k 个最相似或者距离最近的样本 2.根据这 k 个最相似的样本对未知样本进行分类 步骤: 1.对数据进行预处理 ...
- 两数相加(B站看视频总结)
''' 两数相加: 给出两个 非空 的链表用来表示两个非负的整数 各自的位数是按照逆序的方式存储的 每一个节点只能保存 一位数 示例: 输入:(2->4->3) + (5->6-&g ...
- C/C++编程笔记:C语言开发球球大作战(源码分享),你想试试吗?
游戏背景 <球球大作战>是Superpop一款自主研du发的免费手机网络游戏. 以玩家间的实时互动PK产生游戏乐趣为设计宗旨,通过简单的规则将玩家操作直接转化为游戏策略,体验智谋碰撞的战斗 ...
- day17.json模块、时间模块、zipfile模块、tarfile模块
一.json模块 """ 所有的编程语言都能够识别的数据格式叫做json,是字符串 能够通过json序列化成字符串与如下类型: (int float bool str l ...
- .NetCore 配合 Gitlab CI&CD 实践 - 开篇
引言 这是一个系列的文章,讲述的是一个中小型开发团队如何从零开始使用搭建基建 GitLab 代码托管平台,以及使用 GitLab Runner 实现 CI/CD 的故事.本系列通过部署一个完整的 .n ...
- C++Primer学习日记
计划:4.27-4.30 完成IO库.顺序容器两章 4/28 ------------------------------------------------- 为什么要使用using namespa ...
- 曲线生成与求交—Bezier曲线
Bezier曲线生成 法国工程师Pierre Bezier在雷诺公司使用该方法来设计汽车.一条Bezier曲线可以拟合任何数目的控制点. 公式 设\(n+1\)个控制点\(P_0,P_1--P_n\) ...
- 微信公众号里面怎么添加xls
微信公众号里面添加xls的教程 我们都知道创建一个微信公众号,在公众号中发布一些文章是非常简单的,但公众号添加附件下载的功能却被限制,如今可以使用小程序“微附件”进行在公众号中添加附件. 以下是公众号 ...
- 敏捷工具:Scrum板与Kanban如何抉择?敏捷工具:Scrum板与Kanban如何抉择?
Scrum板作为一种工具,主要应用于Scrum团队的敏捷项目管理,能够帮助团队更新任务进度,促进团队信息共享,及时发现任务过程中的异常现象,从而查漏补缺.团队在每日站会时会通过Scrum板来直观地展示 ...