当前位置: 首页 > news >正文

[3.2] 深入了解recv参数列表里的status

文章目录

    • MPI Status & Probe动态的接收
      • 1 MPI_Status结构体查询的范例
      • 2 use MPI_Probe找出消息大小

MPI Status & Probe动态的接收

MPI_RecvMPI_Status结构体的地址作为参数,可以使用MPI_STATUS_IGNORE 忽略。如果我们将 MPI_Status 结构体传递给 MPI_Recv 函数,则操作完成后将在该结构体中填充有关接收操作的其他信息。 三个主要的信息包括:

  • 发送端的rank,发送端的rank存储在结构体MPI_SOURCE元素中,如果声明一个MPI_Status state对象,则可以通过state.MPI_SOURCE访问rank。

    typedef struct MPI_Status {
        int count_lo;                  // 低位的计数值,表示接收到的数据量的低32位(可能与 count_hi_and_cancelled 组合成完整的 64 位计数)
        int count_hi_and_cancelled;    // 高位的计数值(如果存在高32位),同时包含一个“取消标志”位
        int MPI_SOURCE;                // 消息的源进程的 rank(表示接收消息是从哪个进程来的)
        int MPI_TAG;                   // 消息的标签(与发送时指定的标签对应,用于标识消息的类型)
        int MPI_ERROR;                 // 错误码(用于存储接收操作的返回状态,MPI_SUCCESS 表示成功)
    } MPI_Status;
    
  • 消息的标签,同上访问方式,访问MPI_TAG

  • 消息的长度,它在在结构体中没有预定义的元素。我们必须使用 MPI_Get_count 找出消息的长度。

    MPI_Get_count(const MPI_Status *status, MPI_Datatype datatype, int *count)
    

    MPI_Get_count中需要传递 MPI_Status 结构体,消息的 datatype(数据类型),并返回 count。 变量 count 是已接收的 datatype 元素的数目。

1 MPI_Status结构体查询的范例

// mpicc mpi_status.cc -o mpi_status
// mpirun -np 2 ./mpi_status
#include <mpi.h>
#include <iostream>
#include <stdio.h>

int main(int argc, char** argv) {
    MPI_Init(NULL, NULL);
  
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
    if (world_size != 2) {
      fprintf(stderr, "Must use two processes for this example\n");
      MPI_Abort(MPI_COMM_WORLD, 1);
    }
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
  
    const int MAX_NUMBERS = 100;
    int numbers[MAX_NUMBERS];
    int number_amount;
    if (world_rank == 0) {
      // Pick a random amount of integers to send to process one
      srand(time(NULL));
      number_amount = (rand() / (float)RAND_MAX) * MAX_NUMBERS;
      // Send the amount of integers to process one
      MPI_Send(numbers, number_amount, MPI_INT, 1, 0, MPI_COMM_WORLD);
      printf("0 sent %d numbers to 1\n", number_amount);
    } else if (world_rank == 1) {
      MPI_Status status;
      // Receive at most MAX_NUMBERS from process zero
      MPI_Recv(numbers, MAX_NUMBERS, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
      // After receiving the message, check the status to determine how many
      // numbers were actually received
      MPI_Get_count(&status, MPI_INT, &number_amount);
      // Print off the amount of numbers, and also print additional information
      // in the status object
      printf("1 received %d numbers from 0. Message source = %d, tag = %d\n",
             number_amount, status.MPI_SOURCE, status.MPI_TAG);
    }
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Finalize();
    return 0;
}
/******************************************************************
0 sent 91 numbers to 1
0 sent 91 numbers to 1
*******************************************************************/

2 use MPI_Probe找出消息大小

在库文件中的定义如下,可以看到与MPI_Recv很类似。可以使用 MPI_Probe 在实际接收消息之前查询消息大小。除了不接收消息之外,MPI_Probe会阻塞具有匹配标签和发送端的消息。消息可用时,会填充Status。然后,用户可以使用 MPI_Recv 接收实际的消息。

MPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status *status)
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main (int argc, char** argv) {
    MPI_Init(NULL, NULL);

    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size); // Get the number of processes
    if (world_size != 2) {
        fprintf(stderr, "Error: This program requires exactly 2 processes.\n");
        MPI_Abort(MPI_COMM_WORLD, 1);
    }

    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); // Get the rank of the current process

    int number_of_amount = 0;
    if (world_rank == 0) {
        int MAX_NUMBERS = 100;
        int numbers[MAX_NUMBERS];
        srand(time(NULL));
        number_of_amount = (rand() / (float)RAND_MAX) * MAX_NUMBERS;
        MPI_Send(numbers, number_of_amount, MPI_INT, 1, 0, MPI_COMM_WORLD);
        printf("Process %d sent %d numbers to process %d.\n", world_rank, number_of_amount, 1);
    } else if (world_rank == 1) {
        MPI_Status status;
        MPI_Probe(0, 0, MPI_COMM_WORLD, &status);
        MPI_Get_count(&status, MPI_INT, &number_of_amount);
        int* number_buffer = (int*)malloc(sizeof(int) * number_of_amount);
        MPI_Recv(number_buffer, number_of_amount, MPI_INT, 0, 0, MPI_COMM_WORLD,
            MPI_STATUS_IGNORE);
            printf("1 dynamically received %d numbers from 0.\n",
                number_of_amount);
        free(number_buffer);
    }
    MPI_Finalize();
}
/******************************************************************
Process 0 sent 29 numbers to process 1.
1 dynamically received 29 numbers from 0.
*******************************************************************/

MPI_Probe 构成了许多动态 MPI 应用程序的基础。 例如,控制端/执行子程序在交换变量大小的消息时通常会大量使用 MPI_Probe。 作为练习,对 MPI_Recv 进行包装,将 MPI_Probe 用于您可能编写的任何动态应用程序。 它将使代码看起来更美好:-)
下一节将通过完整的代码例子说明send和recv为什么是阻塞通信。

相关文章:

  • 信息系统项目管理中各个知识领域的概要描述及其管理流程
  • 【网络安全】 防火墙技术
  • 卢瑟福实验室2025.4.5
  • java流程控制05:Switch选择结构
  • Python开发GUI 框架TKinter、PyQt、PySide、wxPython、Kivy、PyGTK
  • Day 7
  • 采掘队绩效考核制度与生产管理
  • Angular 2 模板语法详解
  • Ubuntu(CentOS、Rockylinux等)快速进入深度学习pytorch环境
  • 【Redis】背景知识
  • 信息系统项目管理师-第十章-项目进度管理
  • 2-Visual Studio 2022 NET开发Windows桌面软件并连接SQL Server数据库
  • 【前端】【tailwind】「由浅入深」 的方式,从基础概念到高级应用,逐步解析 Tailwind CSS 的分层系统,并设置自己的原子类和组件类
  • 谷歌亮剑:Canvas免费开放,TPU火上浇油!AI大战再掀波澜
  • 讯飞语音合成(流式版)语音专业版高质量的分析
  • vscode和cursor对ubuntu22.04的remote ssh和X-Windows的无密码登录
  • 【深度学习】通过colab将本地的数据集上传到drive
  • Linux_4
  • HTML5 Web Workers 学习笔记
  • DAY 37 leetcode 454--哈希表.四数相加