MPI之通信模式(标准,缓存,同步,就绪)

这篇具有很好参考价值的文章主要介绍了MPI之通信模式(标准,缓存,同步,就绪)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

MPI缓冲区

  • 由MPI自行维护的一块内存区域,也可由用户(MPI_Bsend)自行维护;
  • 发送方 维护一块发送缓冲区; 接收方 维护一块接收缓冲区。

数据收发过程:

MPI之通信模式(标准,缓存,同步,就绪),并行计算,MPI,并行计算,通信模式,标准,缓存,同步,就绪

  • 当发送端将数据拷贝到自身的数据缓冲区后(注意这里是拷贝,即数据到达发送缓冲区,再对原数据进行修改将不会影响发送的数据),对应的Send函数将会返回,意味着发送动作已经完成;
  • 当接收端将数据拷贝到自身的接收缓冲区中,Recv函数调用结束。

类似于Socket通信时,调用send将数据放置发送缓冲区即表示send完成。

阻塞通信模型

发送

1. 标准通信模式 MPI_Send 该接口是否进行缓存由MPI决定,分情况讨论
  1. 发送进程的发送动作不依赖接收进程(有缓存):发送进程将数据拷贝到数据缓冲区,不管接收进程有没有执行接收动作,函数都直接返回,发送动作对于用户来讲已经完成;
  2. 发送进程的发送动作依赖于接收进程(不带缓存,直接发送):发送进程发送消息时需要接收进程也要开始接收进程,两者处于一边发送一边接收的状态,此时MPI_Send阻塞当前发送方直到数据被接收方确认收到,基于底层的数据传输机制;
    MPI之通信模式(标准,缓存,同步,就绪),并行计算,MPI,并行计算,通信模式,标准,缓存,同步,就绪
2. 缓存通信模式 MPI_Bsend 当用户对上述标准通信模式不满意,不能满足需求,可以采用该模式

该函数在发送消息时使用明确的缓冲区,并具有较低的内存使用率和较高的性能。相对于 MPI_Send 函数,MPI_Bsend 不阻塞发送方,也不会复制消息缓冲区中的数据,而是将数据拷贝到MPI缓冲区中,MPI_Bsend 函数将立即返回,在MPI缓冲区中的消息稍后使用异步方式传输。

函数原型

int MPI_Bsend(const void *buf, int count, 
MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
//用户自行管理缓冲区
int MPI_Buffer_attach(void *buffer,int size)
int MPI_Buffer_detach(void *buffer,int &size)

参数详解

  • buf: 待发送数据的首地址
  • count: 待发送的数据量
  • datatype: 待发送数据类型
  • dest: 目标进程的 MPI rank
  • tag: 消息标记
  • comm: MPI通信域

注意事项
发送时需要将数据从消息缓冲区拷贝到用户提供的缓冲区buffer,该方法消除了发送端同步的开销,如前面分析,消息发送能否进行及能否正确返回不依赖于接收进程。好处是用户可以认为程序需要发送的消息提供缓冲区,但用户也需要负责管理该缓冲区。如果该缓冲区buffer大小不足以存储消息缓冲区中待发送的数据,将导致程序错误退出

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

#define BUFFER_SIZE  1024

int main(int argc, char *argv[])
{
    int rank, size;
    MPI_Status status;
    double t0, t1;
    char buf[BUFFER_SIZE];
    char *my_buffer;
    MPI_Request request;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    if(rank == 0)
    {
        //为MPI缓冲区分配内存空间
        my_buffer=(char *)malloc(BUFFER_SIZE);
        MPI_Buffer_attach(my_buffer, BUFFER_SIZE);

        snprintf(buf, BUFFER_SIZE, "Hello, world, from rank %d!", rank);
        t0=MPI_Wtime();
        //异步发送消息
        MPI_Bsend(buf, BUFFER_SIZE, MPI_CHAR, 1, 0, MPI_COMM_WORLD, &request);
        MPI_Wait(&request, &status);
        t1=MPI_Wtime();
        printf("Time taken=%f\n", t1-t0);

        free(my_buffer);
        MPI_Buffer_detach(&my_buffer, &BUFFER_SIZE);
    }
    else
    {
        //为MPI缓冲区分配内存空间
        my_buffer=(char *)malloc(BUFFER_SIZE);
        MPI_Buffer_attach(my_buffer, BUFFER_SIZE);

        t0=MPI_Wtime();
        //等待接收消息
        MPI_Recv(buf, BUFFER_SIZE, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &status);
        t1=MPI_Wtime();
        printf("Rank %d received message=%s, time=%f\n", rank, buf, t1-t0);

        free(my_buffer);
        MPI_Buffer_detach(&my_buffer, &BUFFER_SIZE);
    }

    MPI_Finalize();
    return 0;
}
3. 同步通信模式 MPI_Ssend

该模式的开始不依赖接收进程相应的接收操作是否已经启动,但是同步发送却必须等到相应的接收进程开始后才可以正确返回。即

  • 发送方必须等待接收方的确认才能继续执行。
  • 接收方必须收到消息后才能继续执行。
  • 可以确保接收方正确接收消息。

MPI之通信模式(标准,缓存,同步,就绪),并行计算,MPI,并行计算,通信模式,标准,缓存,同步,就绪
函数原型

int MPI_Ssend(void* buf, int count, MPI_Datatype datatype, 
int dest, int tag, MPI_Comm comm)

参数详解

  • buf:指向待发送数据的指针。
  • count:发送元素数量。
  • datatype:发送元素的类型。
  • dest:目标进程的进程号。
  • tag:消息标签。
  • comm:进程通信域

代码示例

#include <stdio.h>
#include <mpi.h>

int main(int argc, char** argv) {
    int size, rank;
    int data;
    MPI_Status status;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
        data = 12345;
        MPI_Ssend(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
        printf("Process 0 sent data %d to process 1\n", data);
    } else if (rank == 1) {
        MPI_Recv(&data, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
        printf("Process 1 received data %d from process 0\n", data);
    }

    MPI_Finalize();
    return 0;
}    
4. 就绪通信模式 MPI_Rsend

该模式只有当接收进程的接收操作已经启动时才可以在发送进程启动发送操作(即是一种发送并立即返回操作),否则,当发送操作启动而相应的操作还没有启动时,发送操作将出错,对于非阻塞发送操作的正确返回,并不意味着发送已经完成,但对于阻塞发送的正确返回,则代表发送缓冲区可以重复使用。

函数原型

int MPI_Rsend(const void *buf, int count, MPI_Datatype datatype, 
int dest, int tag, MPI_Comm comm)

参数详解

  • buf:指向待发送数据的指针。
  • count:发送元素数量。
  • datatype:发送元素的类型。
  • dest:目标进程的进程号。
  • tag:消息标签。
  • comm:进程通信域

代码实例

#include <stdio.h>
#include <mpi.h>

int main(int argc, char** argv) {
    int size, rank;
    int data;
    MPI_Status status;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == 0) {
        data = 12345;
        MPI_Request request;
        MPI_Rsend(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
        printf("Process 0 sent data %d to process 1\n", data);
    } else if (rank == 1) {
        MPI_Status status;
        int data_recv;
        MPI_Recv(&data_recv, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
        printf("Process 1 received data %d from process 0\n", data_recv);
    }

    MPI_Finalize();
    return 0;
}

接收

  • MPI_Recv

非阻塞通信模式

发送

标准通信模式 MPI_Isend
缓存通信模式 MPI_Ibsend

是 MPI_Bsend 的非阻塞版本,在 MPI_Bsend 的基础上,MPI_Ibsend 函数允许发送方在消息发送期间继续执行其他操作,而不必等待消息发送完成。MPI_Ibsend 函数将消息存储在缓冲区中,并返回一个 MPI_Request 对象,代表着消息的发送请求。
函数原型

int MPI_Ibsend(const void* buf, int count, 
MPI_Datatype datatype, int dest, int tag, 
MPI_Comm comm, MPI_Request* request)

参数详解

  • buf:指向待发送数据的指针。
  • count:发送元素数量。
  • datatype:发送元素的类型。
  • dest:目标进程的进程号。
  • tag:消息标签。
  • comm:进程通信域。
  • request:MPI_Request 类型的指针,存储发送请求对象。

代码实例

#include <stdio.h>
#include <mpi.h>

#define BUFFER_SIZE 1024

int main(int argc, char** argv) {
    int size, rank;
    int data;
    MPI_Status status;
    char buffer[BUFFER_SIZE];
    MPI_Request request;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == 0) {
        data = 12345;
        MPI_Buffer_attach(buffer, BUFFER_SIZE);
        MPI_Ibsend(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request);
        printf("Process 0 sent data %d to process 1\n", data);
        MPI_Wait(&request, &status);
        MPI_Buffer_detach(buffer, &BUFFER_SIZE);
    } else if (rank == 1) {
        int data_recv;
        MPI_Recv(&data_recv, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
        printf("Process 1 received data %d from process 0\n", data_recv);
    }

    MPI_Finalize();
    return 0;
}
同步通信模式 MPI_Issend

MPI_Ssend 的非阻塞版本,在 MPI_Ssend 的基础上,MPI_Issend 函数允许发送方在消息发送期间继续执行其他操作,而不必等待消息发送完成。MPI_Issend 函数将消息存储在缓冲区中,并返回一个 MPI_Request 对象,代表着消息的发送请求。
函数原型

int MPI_Issend(const void* buf, int count, 
MPI_Datatype datatype, int dest, int tag, 
MPI_Comm comm, MPI_Request* request)

参数详解

  • buf:指向待发送数据的指针。
  • count:发送元素数量。
  • datatype:发送元素的类型。
  • dest:目标进程的进程号。
  • tag:消息标签。
  • comm:进程通信域。
  • request:MPI_Request 类型的指针,存储发送请求对象。

代码实例

#include <stdio.h>
#include <mpi.h>

#define BUFFER_SIZE 1024

int main(int argc, char** argv) {
  int size, rank;
  int data;
  MPI_Status status;
  char buffer[BUFFER_SIZE];
  MPI_Request request;

  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  if (rank == 0) {
    data = 12345;
    MPI_Buffer_attach(buffer, BUFFER_SIZE);
    MPI_Issend(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request);
    printf("Process 0 sent data %d to process 1\n", data);
    MPI_Wait(&request, &status);
    MPI_Buffer_detach(buffer, &BUFFER_SIZE);
  } else if (rank == 1) {
    int data_recv;
    MPI_Recv(&data_recv, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
   printf("Process 1 received data %d from process 0\n", data_recv);
  }

  MPI_Finalize();
  return 0;
}
就绪通信模式 MPI_Irsend

是 MPI_Rsend 的非阻塞版本,在 MPI_Rsend 的基础上,MPI_Irsend 函数允许发送方在消息发送期间继续执行其他操作,而不必等待消息发送完成。MPI_Irsend 函数将消息存储在缓冲区中,并返回一个 MPI_Request 对象,代表着消息的发送请求。
函数原型

int MPI_Irsend(const void* buf, int count, 
MPI_Datatype datatype, int dest, int tag, 
MPI_Comm comm, MPI_Request* request)

参数详解

  • buf:指向待发送数据的指针。
  • count:发送元素数量。
  • datatype:发送元素的类型。
  • dest:目标进程的进程号。
  • tag:消息标签。
  • comm:进程通信域。
  • request:MPI_Request 类型的指针,存储发送请求对象。

代码实例

#include <stdio.h>
#include <mpi.h>

#define BUFFER_SIZE 1024

int main(int argc, char** argv) {
  int size, rank;
  int data;
  MPI_Status status;
  char buffer[BUFFER_SIZE];
  MPI_Request request;

  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  if (rank == 0) {
    data = 12345;
    MPI_Buffer_attach(buffer, BUFFER_SIZE);
    MPI_Irsend(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request);
    printf("Process 0 sent data %d to process 1\n", data);
    MPI_Wait(&request, &status);
    MPI_Buffer_detach(buffer, &BUFFER_SIZE);
  } else if (rank == 1) {
    int data_recv;
    MPI_Recv(&data_recv, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
     printf("Process 1 received data %d from process 0\n", data_recv);
  }

  MPI_Finalize();
  return 0;
}

注,MPI_Irsend 的缓冲区大小由 MPI_BSEND_BUFFER_SIZE 宏定义所决定。如果发送的消息大于缓冲区大小,将会导致 MPI_Irsend 函数阻塞

接收

  • MPI_Irecv

区别:

  1. 是否要对发送的数据进行缓存;(缓存)
  2. 是否只有当接收调用执行后才可以执行发送操作;(同步)
  3. 什么时候发送调用可以正确返回;
  4. 发送调用正确返回是否意味着发送已完成。

几种特殊使用场景

短时间内有大量的短消息的发送

可能会导致缓冲区爆掉,导致消息丢失,用户可能需要使用MPI_Bsend控制缓冲区的使用;
如果短消息可以打包成一个大消息,降低发送次数

发送的数据量特别大

MPI提供的缓冲区的大小不够,可能导致数据丢失,从而导致程序卡,MPI_Bsend模式来直接控制缓冲区的使用;

可以进行分段发送,对数据进程拆分。文章来源地址https://www.toymoban.com/news/detail-691143.html

到了这里,关于MPI之通信模式(标准,缓存,同步,就绪)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 矩阵乘法的MPI并行实验报告

    (1) 分别用 1,2,4,8 个进程完成矩阵乘法(同一个程序):A * B = C,其中 A,B,C 均为 2048*2048 双精度点方阵,0号进程负责初始化矩阵 A,B 并将结果存入 0 号进程。 (2) 绘制加速比曲线; 操作系统:Windows11 编程语言:C++(使用MPI接口) 编译器:VC++ 核心库:MPI(MSMPI)

    2024年02月08日
    浏览(35)
  • 使用mpi并行技术实现快排Qsort()

    快排基本原理: 快速排序可以说是最为常见的排序算法,冒泡排序时间复杂度达到了O(N2),而桶排序容易造成浪费空间。快排(Quicksort)就成为了不错的选择。 1、原理:快排需要找一个数作为基准数,用来参照。(可取第一个数为参照)         基准数在中间某位置,

    2024年02月10日
    浏览(31)
  • CUDA 以及MPI并行矩阵乘连接服务器运算vscode配置

    本地安装 服务器端安装 c_cpp_properties.json launch.json tasks.json     本地安装和服务器端安装的扩展和CUDA一样 c_cpp_properties.json launch.json settings.json tasks.json

    2024年04月27日
    浏览(30)
  • IGH主站通信测试csp模式(DC同步 preemrt)连通一从站并实现控制

    linuxcnc配置基础机器人控制LinuxCNC与EtherCAT介绍PDOSDO,搭建环境步骤 需要配置IGH主站的查看这篇文章 linux系统学习笔记7——一次性安装igh-ethercat主站 CSP模式 DC同步方式 preemrt实时补丁 直接上代码,这部分是直接控制使用csp模式控制一个从站运动 使能后直接运动,10s,每秒60

    2024年01月16日
    浏览(39)
  • 用FPGA驱动FT602芯片实现USB3.0UVC 相机彩条视频输出试验,使用同步245模式通信

    FPGA USB3.0 UVC工业相机 本设计用FPGA驱动FT602芯片实现USB3.0UVC 相机彩条视频输出试验,使用同步245模式通信,提供vivado工程源码,用verilog代码生成的彩条视频经过图像三帧缓存至DDR3后读出,经过RGB转YUV送入UVC模块,经FT602芯片的USB3.0接口输出到电脑主机,电脑端用FT602官方的软

    2024年01月25日
    浏览(39)
  • 云计算与大数据——MPI集群配置

    MPI(消息传递接口)是一种用于编写并行程序的标准,它允许在多个计算节点上进行通信和协作。MPI集群配置是指在一个或多个计算节点上设置MPI环境以实现并行计算。 MPI集群配置的步骤: 硬件选型:选择适合你需求的硬件设备,包括主节点和计算节点。主节点负责协调计

    2024年02月16日
    浏览(37)
  • Python 标准类库-并发执行之multiprocessing-基于进程的并行

    Python3.6 multiprocessing 是一个支持使用类似于线程模块的API派生进程的包。该包同时提供本地和远程并发,通过使用子进程而不是线程,有效地避开了全局解释器锁。因此, multiprocessing 模块允许程序员充分利用给定机器上的多个处理器。它同时在Unix和Windows上运行。 该模块还引

    2024年02月09日
    浏览(24)
  • 大数据与云计算——MPI集群配置(全网最详细讲解)

    MPI(消息传递接口)是一种用于编写并行程序的标准,它允许在多个计算节点上进行通信和协作。MPI集群配置是指在一个或多个计算节点上设置MPI环境以实现并行计算。 MPI集群配置的步骤: 硬件选型:选择适合你需求的硬件设备,包括主节点和计算节点。主节点负责协调计

    2024年02月04日
    浏览(33)
  • 高性能计算的矩阵乘法优化 - Python +MPI的实现

    本次实验的目的是使用MPI的并行性来进行矩阵乘法优化,本人使用 Python 实现 实验硬件: CPU :AMD Ryzen 7 5800H(3.20 GHz) 内存 :32GB (3200MHz) 要求 :使用一个矩阵,一个向量相乘,分别用单进程和多进程的mpi接口实现。 全局的规模参数是 Scale 数据示例 : 当 Scale=5 时,数据示例如

    2023年04月22日
    浏览(85)
  • STM32F103单片机通过SPI全双工通信协议与W25Q64(FLASH)进行通信【串行同步通信(数据线与时钟线配合),(一主多从模式)】附相关驱动代码详解

    1.W25Qxx系列是一种低成本、小型化、使用简单的 非易失性存储器 ,常应用于数据存储、字库存储、固件程序存储等场景 2.存储介质: Nor Flash(闪存) 3.时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI) 4.存储容量(24位地址): W25Q40: 4Mbit / 512KByte W25Q80: 8Mbit / 1MByte W25Q16: 16

    2024年04月13日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包