MPI点对点标准通信
1.先来熟悉一下MPI运行环境以及进程分配
/*
* MPI hello
* MPI_COMM_WORLD
* MPI_Init & MPI_Finalize & MPI_Comm_size & MPI_Comm_rank
*
*/
#include<stdio.h>
#include<mpi.h>
int main()
{
// 用来标记当前进程号
int my_rank;
// 用来表示通信进程集和总数
int comm_size;
// 初始化mpi执行环境
MPI_Init(NULL,NULL);
// MPI_COMM_WORLD为进程集和,由MPI_Init()函数创建,它的大小由启动参数决定
// 如mpiexec -n 10 ./exec,则通信集和的大小为为10
// 获取当前进程号
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
// 获取启动进程总数
MPI_Comm_size(MPI_COMM_WORLD,&comm_size);
if(my_rank==0)
printf("总共有%d个进程\n",comm_size);
printf("你好,我是%d号进程。\n",my_rank);
// 释放mpi运行环境所占的资源
MPI_Finalize();
return 0;
}
2.MPI点对点标准阻塞通信
/*
* MPI点对点通信
* 标准模式,阻塞式
* MPI_Send & MPI_Recv
*/
#include<stdio.h>
#include<mpi.h>
int main()
{
int my_rank;
int comm_size;
MPI_Init(NULL,NULL);
MPI_Comm_size(MPI_COMM_WORLD,&comm_size);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
// 关键函数
// MPI_Send(要发送消息的地址,消息的大小,消息的类型,指定接受的进程号,消息的标志,通信集和)
// MPI_Recv(用来保存消息的地址,消息的大小,消息的类型,发送消息的进程号,消息的标志,通信集和,状态信息)
// 其它进程向0号进程发送消息
if(my_rank!=0)
{
// 发送消息给0号进程,消息内容为当前进程号
MPI_Send(&my_rank,1,MPI_INT,0,0,MPI_COMM_WORLD);
}
// 0号进程接收消息
else
{
// 若启动了一个进程,则没有消息传送
if(comm_size==1)
{
printf("只有我这一个进程,没有进程向我发消息\n");
}
else
{
int i;
// 用来存放消息来源进程号
int other_rank;
for(i=1;i<comm_size;i++)
{
// 0号进程接收消息,根据消息内容(其它进程号)判断是哪个进程发来的消息,打印信息
MPI_Recv(&other_rank,1,MPI_INT,i,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
printf("进程%d发来消息\n",other_rank);
}
}
}
MPI_Finalize();
return 0;
}
3.MPI点对点标准非阻塞通信
/*
* MPI点对点非阻塞通信
*
* 阻塞与非阻塞的区别(简单描述)
* 举个例子,你要烧一壶水,在烧水的过程中你可以去做其它的事情,那么就算非阻塞的
* 若你一直在水壶旁等水烧开,那就是阻塞的
* 再比若MPI函数发送消息,消息量可能很大,可能会很耗时间,
* 若进程一直等待,直到消息发送完才去做其它事情,那就是阻塞的
* 若进程开始发送消息后,不等消息发送完,就可以去做其它事情,那就是非阻塞的
*
* MPI_Isend & MPI_Irecv & MPI_Wait & MPI_Test & MPI_Request & MPI_Status
*
* MPI_Isend() 与 MPI_Send(),MPI_Irecv() 与 MPI_Recv() 大致相同
* 多了一个MPI_Request参数
* MPI_Isend( , , , , , ,MPI_Request)
* 少了一个MPI_Status参数,多了一个MPI_Request参数
* MPI_Irecv( , , , , , ,MPI_Request)
*
* 阻塞式
* 等待请求完成
* MPI_Wait(MPI_Request*, MPI_Status*)
* 非阻塞式
* 测试请求是否完成
* MPI_Test(MPI_Request*, int* flag, MPI_Status*)
* if flag==1 则请求已完成
*
*/
#include<stdio.h>
#include<mpi.h>
int main()
{
int comm_size;
int my_rank;
MPI_Init(NULL,NULL);
MPI_Comm_size(MPI_COMM_WORLD,&comm_size);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Request request;
MPI_Status status;
//0号进程向1号进程发送消息
if(my_rank==0)
{
// MPI把一次非阻塞消息发送看作一次请求(可能是把这项任务交给操作系统去做,不太清楚),请求信息保存在request中
MPI_Isend(&my_rank,1,MPI_INT,1,0,MPI_COMM_WORLD,&request);
}
// 1号进程接收0号进程发送来的消息,并打印
else if(my_rank==1)
{
int tmp;
// MPI把一次非阻塞消息接收也看作一次请求,请求信息保存在request中
MPI_Irecv(&tmp,1,MPI_INT,0,0,MPI_COMM_WORLD,&request);
// 阻塞式函数,等待消息发送请求完成
// status是请求进度的状态信息
MPI_Wait(&request,&status);
// int flag=0;
// MPI_Test(&request,&flag,&status);
// if(flag){ printf("接收完成"); }
printf("message:%d\n",tmp);
}
MPI_Finalize();
return 0;
}
最后,欢迎大家加入MPI-OpenMP技术交流群,群号:288514428