学习了MPI四种通信模式 及其函数用法:

(1)标准通信模式:MPI_SEND

(2)缓存通信模式:MPI_BSEND

(3)同步通信模式:MPI_SSEND

(4)就绪通信模式:MPI_RSEND

四种通信模式的区别都在消息发送端,而消息接收端的操作都是MPI_RECV。

1.标准通信模式

原理图如下

标准通信模式由MPI决定是否用缓存。

如果MPI决定缓存将要发出的数据:发送操作不管接受操作是否执行,都可以进行;而且缓存结束后发送操作就可以返回,不需要等待接受操作收到数据

如果MPI决定不缓存将要发送的数据:对于阻塞通信,则要求接受操作执行,并且数据都发送到接受缓冲区了,发送操作才能够返回;对于非阻塞通信,发送操作虽然没有完成,但是发送调用可以正确返回。

2.缓存通信模式

与标准通信的区别在于需要自己维护程序的缓冲区。

int MPI_Buffer_attach(void *buffer, int size)用于申请缓存

int MPI_Buffer_detach(void **buffer, int *size) 用于释放缓存 这是一个阻塞调用 函数返回表示缓冲区已经被释放

示例代码如下:

 #include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#define SIZE 6
static int src = ;
static int dest = ; void generate_data(double *, int);
void normal_recv(double *, int);
void buffered_send(double *, int); void generate_data(double *buffer, int buff_size){
int i;
for (i=; i<buff_size; i++) buffer[i]=(double)i+;
} void normal_recv(double *buffer, int buff_size){
int i,j;
MPI_Status status;
double *b; b = buffer; MPI_Recv(b,(buff_size-),MPI_DOUBLE,src,,MPI_COMM_WORLD, &status);
fprintf(stderr, "standard receive a message of %d data\n", buff_size-);
for(j=; j<buff_size-; j++) fprintf(stderr, "buf[%d]=%f\n",j,b[j]); b+=buff_size-;
MPI_Recv(b, , MPI_DOUBLE, src, , MPI_COMM_WORLD, &status);
fprintf(stderr, "standard receive a message of one data\n");
fprintf(stderr, "buf[0]=%f\n",*b);
} void buffered_send(double *buffer, int buff_size){
int i,j;
void *bbuffer;
int size; fprintf(stderr, "buffered send message of %d data\n", buff_size-);
for(j=; j<buff_size-; j++) fprintf(stderr, "buf[%d]=%f\n",j,buffer[j]);
MPI_Bsend(buffer, (buff_size-), MPI_DOUBLE, dest, , MPI_COMM_WORLD); buffer+=buff_size-;
fprintf(stderr, "bufferred send message of one data\n");
fprintf(stderr, "buf[0]=%f\n", *buffer);
MPI_Bsend(buffer, , MPI_DOUBLE, dest, , MPI_COMM_WORLD); MPI_Buffer_detach(&buffer, &size);
MPI_Buffer_attach(bbuffer, size);
} int main(int argc, char *argv[])
{
int rank;
double buffer[SIZE], *tmpbuffer, *tmpbuf;
int tsize, bsize;
char *test = NULL; MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank==src) { // 发送消息进程
generate_data(buffer, SIZE);
MPI_Pack_size(SIZE, MPI_DOUBLE, MPI_COMM_WORLD, &bsize);
tmpbuffer = (double*)malloc(bsize+*MPI_BSEND_OVERHEAD);
if (!tmpbuffer) {
MPI_Abort(MPI_COMM_WORLD, );
}
// 告诉系统MPI_Bsend用到buffer就去tmpbuffer那里去找
MPI_Buffer_attach(tmpbuffer, bsize+*MPI_BSEND_OVERHEAD);
buffered_send(buffer, SIZE);
MPI_Buffer_detach(&tmpbuf, &tsize);
printf("tsize detach from tmpbuf is : %d\n", tsize);
}
else if (rank==dest) {
normal_recv(buffer, SIZE);
}
else {
MPI_Abort(MPI_COMM_WORLD, );
}
MPI_Finalize();
}

代码输出结果是:

总共需要发送5个double类型,每个类型占8个字节;MPI通信其他附属信息占200个字节;因此总共缓冲区的大小的240个字节。

3.同步通信模式

同步发送进程的特点是:发送操作可以不依赖接受进程的相应接受操作是否已经启动,但是必须等着接受操作开始执行后才能返回;这意味着一旦同步发送返回后,发送缓冲区中的数据已经全部被系统缓冲区缓存。“发送缓冲区”表示MPI的缓冲区,“系统缓冲区”指的是操作系统的写缓冲区,注意二者的区别。这意味着同步发送缓冲区中的数据可以被释放或重新利用。而标准通信模式(或缓存通信模式)中,在用缓存的模式下,发送操作返回仅仅意味着数据都已经到发送缓冲区中了,数据是否到系统缓冲区不得知。

示例代码如下:

 #include "mpi.h"
#include <stdio.h> #define SIZE 10 static int src = ;
static int dest = ; int main(int argc, char *argv[])
{
int rank;
int act_size = ;
int flag, np, rval, i;
int buffer[SIZE];
MPI_Status status, status1, status2;
int count1, count2;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &np); if (np!=) {
MPI_Abort(MPI_COMM_WORLD, );
}
act_size = ; /*最大消息长度*/
if (rank==src) {
MPI_Ssend(buffer, act_size, MPI_INT, dest, , MPI_COMM_WORLD);
fprintf(stderr, "MPI_Ssend %d data,tag=1\n", act_size);
act_size = ;
MPI_Ssend(buffer, act_size, MPI_INT, dest, , MPI_COMM_WORLD);
fprintf(stderr, "MPI_Ssend %d data,tag=2\n", act_size);
}
else if (rank=dest) {
MPI_Recv(buffer, act_size, MPI_INT, src, , MPI_COMM_WORLD, &status1);
MPI_Recv(buffer, act_size, MPI_INT, src, , MPI_COMM_WORLD, &status2);
MPI_Get_count(&status1, MPI_INT, &count1);
fprintf(stderr, "receive %d data,tag=%d\n",count1, status1.MPI_TAG);
MPI_Get_count(&status2, MPI_INT, &count2);
fprintf(stderr, "receive %d data,tag=%d\n",count2, status2.MPI_TAG);
}
MPI_Finalize();
}

代码执行结果如下:

如果将33 34行代码互换位置,则程序陷入了deadlock:一方面发送进程中tag=1的MPI_Ssend操作一直处于阻塞状态;另一方面接受进程中的tag=2的MPI_Recv操作处于阻塞状态;两个进程互相等着对方,陷入了死锁。

4. 就绪通信模式

与前几种通信模式不同,只有当接受进程的接受操作已经启动时,才可以在发送端启动发送进程。

一种可能的就绪通信模式实现方法如下图:

上图保证的目标是①要先于④执行;方法是插入②和③;①一定先于②执行,③一定等②成功后才能执行,③成功后④才能执行。

由此一定保证①先于④执行,就保证了就绪通信。

示例代码如下:

 #include "mpi.h"
#include <stdio.h>
#include <stdlib.h> #define TEST_SIZE 2000 void test_rsend(); int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
test_rsend();
MPI_Finalize();
} void test_rsend()
{
int rank, size;
int next, prev;
int tag;
int count;
float send_buf[TEST_SIZE], recv_buf[TEST_SIZE];
MPI_Status status;
MPI_Request request; MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size); if (!=size) {
MPI_Abort(MPI_COMM_WORLD, );
}
next = rank + ;
if (next >= size) next = ;
prev = rank - ;
if (prev <) prev = size-; if (==rank) {
fprintf(stderr, " Rsend Test\n");
}
tag = ;
count = TEST_SIZE/;
if (==rank) {
MPI_Recv(MPI_BOTTOM,,MPI_INT,next,tag,MPI_COMM_WORLD, &status);
fprintf(stderr, " Process %d post Ready send\n", rank);
MPI_Rsend(send_buf,count,MPI_FLOAT,next,tag,MPI_COMM_WORLD);
}
else {
fprintf(stderr, " process %d post a receive call\n", rank);
MPI_Irecv(recv_buf, TEST_SIZE, MPI_FLOAT,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&request);
MPI_Send(MPI_BOTTOM,,MPI_INT,next,tag,MPI_COMM_WORLD);
MPI_Wait(&request, &status);
fprintf(stderr, " Process %d Receive Rsend message from %d\n",rank, status.MPI_SOURCE);
}
}

代码执行结果如下:

【MPI学习3】MPI并行程序设计模式:不同通信模式MPI并行程序的设计的更多相关文章

  1. 【MPI学习2】MPI并行程序设计模式:对等模式 & 主从模式

    这里的内容主要是都志辉老师<高性能计算之并行编程技术——MPI并行程序设计> 书上有一些代码是FORTAN的,我在学习的过程中,将其都转换成C的代码,便于统一记录. 这章内容分为两个部分: ...

  2. 程序设计模式 —— State 状态模式

    我应该如何阅读? 本文将使用优雅的文字风格来告诉你什么是状态模式. 注意: 1.在阅读本文之前请保证你已经掌控了 面对对象的思想与 多态的基本概念,否则将难以理解. 2.本文实现将用C++实现,你不一 ...

  3. MPI学习笔记(三):矩阵相乘的分块并行(行列划分法)

    mpi矩阵乘法:C=αAB+βC 一.主从模式的行列划分并行法 1.实现方法 将可用于计算的进程数comm_sz分解为a*b,然后将矩阵A全体行划分为a个部分,将矩阵B全体列划分为b个部分,从而将整个 ...

  4. 学习记录:《C++设计模式——李建忠主讲》2.面向对象设计原则

    1.课程内容: 重新认识面向对象:面向对象设计原则: 2.重新认识面向对象 1)理解隔离变化:从宏观层面来看,面向对象的构建方式更能适应软件的变化,将变化所带来的影响减为最小: 2)各司其职:从微观层 ...

  5. 探究osg中的程序设计模式【目录】

    前序 探究osg中的程序设计模式---开篇 探究osg中的程序设计模式---创造性模式 探究osg中的程序设计模式---创造型模式---Factory(工厂)模式 探究osg中的程序设计模式---创造 ...

  6. [转][osg]探究osg中的程序设计模式【目录】

    作者:3wwang 原文接连:http://www.3wwang.cn/html/article_104.html 前序 探究osg中的程序设计模式---开篇 探究osg中的程序设计模式---创造性模 ...

  7. Java常见设计模式之工厂模式

    工厂模式在我们日常的应用中应当算是比较广泛的一种设计模式了.今天让我们一起来学习一下,工厂的设计模式. 工厂模式在<Java与模式>中分为三类:     1)简单工厂模式(Simple F ...

  8. java面试题之----jdbc中使用的设计模式(桥接模式)

    1.JDBC(JavaDatabase Connectivity) JDBC是以统一方式访问数据库的API. 它提供了独立于平台的数据库访问,也就是说,有了JDBC API,我们就不必为访问Oracl ...

  9. 【设计模式】Java设计模式 - 装饰者模式

    Java设计模式 - 装饰者模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自 ...

随机推荐

  1. FPGA speed grade

    Altera的-6.-7.-8速度等级逆向排序,Xilinx速度等级正向排序. 不很严密地说,“序号越低,速度等级越高”这是Altera FPGA的排序方法, “序号越高,速度等级也越高”这是Xili ...

  2. Android程序入口以及项目文件夹的含义和使用总结—入门

    新接触一门程序或者开发框架,我一般都要先弄清楚程序的入口在哪里,程序怎么运行的:建立一个项目后,各个文件夹有什么作用以及如何使用等等.理清楚这些东西对以后开发是很有好处的,古话说得好,工欲善其事,必先 ...

  3. netty-socketio使用namespace

    一.简介 netty-socketio中的namespace可以用于区别在相同连接地址下的不同用户,当两个不同的用户打开同一个页面的时候,可以使用namespace用来标记不同用户.例如我们可以在用户 ...

  4. RTB交接

    RTB产品测试进度 元数RTB产品 元数的产品已经测过两个版本,分别是1.1版本和1.2版本,目前线上跑的是1.2版本.程序线上情况目前正常,没有问题. 元数功能账号为:yuanshu  需用root ...

  5. (转载)APP测试点总结

    以下所有测试最后必须在真机上完整的执行1.安装.卸载测试 在真机上的以及通过91等第三方的安装与卸载 安装在手机上还是sd卡上 2.启动app测试3.升级测试 数字签名.升级覆盖安装.下载后手动覆盖安 ...

  6. 华硕飞行堡垒zx50安装Ubunutu折腾记

    今年8月入手了华硕zx50,配置不错,作为一个合格的Linux爱好者,没买来一台电脑肯定得装上Linux编个程序什么的吧,,可恶的是,笔记本安装Linux系统往往比较麻烦,必须折腾很久才安装上,我手上 ...

  7. 非常全面的讲解Hosts文件

    很奇怪有很多人不知道Hosts是什么东西.在网络病毒日渐盛行的今天,认识Hosts其实是很有用的,因为有好多的网页木马都盯上了这个文件,而在很多时候,您只需打开这个文件做一个小小的修改,就完全可以解决 ...

  8. DimDate populate data

    日期维度 任何一个数据仓库都应该有一个日期维度. 因为很少有不需要通过日期维度看数据的情况存在. 日期维度的好处是,你可以通过他连接各个事实表,然后在报表端传送报表参数的时候, 直接自动过滤日期维度的 ...

  9. openfire+asmack搭建的安卓即时通讯(四) 15.4.10

    之前的教程不知道你们成功了没,,,没成功可以问我啊=-= 第四篇博文是要实现发送消息的功能. 首先在我们登陆后的活动的layout里添加这样的两个控件,一个EditText和一个Button用于发送数 ...

  10. 【OpenCV】全景拼接

    从OpenCV3.0正式版开始,features2d中的一些接口,搬到附加库xfeatures2d中了,其中就有SIFT.SURF的特征检测方法,但是正常下载安装OpenCV并不包含附加库,因为附加库 ...