【MPI】 六大金刚:六个最基本、最常用的函数

【MPI】 六大金刚:六个最基本、最常用的函数

首先,安装MPI看这里

这6个函数API如下:

/* Initialize and Finalize */
int MPI_Init(int *argc, char ***argv)
int MPI_Finalize()

/* MPI comm size and rank */
int MPI_Comm_size(MPI_Comm comm, int *size)
int MPI_Comm_rank(MPI_Comm comm, int *rank)

/* MPI send and recv */
int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest,
             int tag, MPI_Comm comm)
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag,
             MPI_Comm comm, MPI_Status *status)

先简要介绍一下 rank (进程序号)和 communicator (通信域):

Rank

  • 定义:在 MPI 中,rank 是一个整数值,用来唯一标识一个进程在特定通信子中的位置。
  • 作用:rank 使得进程能够被唯一地识别,从而可以在通信时指定具体的发送者或接收者。
  • 获取方式:通过 MPI_Comm_rank 函数可以获得当前进程在某个通信子中的 rank。

Communicator

  • 定义communicator 是一组进程的集合,这些进程共享一个通信上下文,可以相互通信。
  • 作用:定义了哪些进程可以相互通信,并提供了这些进程间通信的环境。
  • 默认通信子MPI_COMM_WORLD 是最常见的默认通信子,它包含了启动 MPI 程序的所有进程。
  • 获取大小:通过 MPI_Comm_size 函数可以知道某个通信子中包含了多少个进程。

简而言之,rank 是进程在通信子中的编号,而 communicator 是一组进程及其通信规则的集合。这两个概念是 MPI 编程中进程间通信的基础。


MPI_Init

MPI_Init 用于初始化 MPI 环境,是 MPI 程序开始执行的第一步。它负责设置 MPI 库,使进程能够参与到 MPI 通信中来。

函数原型
int MPI_Init(int *argc, char ***argv);
参数
  • argc:指向命令行参数计数的指针。通常,这是传给主函数 main 的第一个参数。
  • argv:指向命令行参数数组的指针。通常,这是传给主函数 main 的第二个参数。
返回值
  • 成功时返回 MPI_SUCCESS
  • 发生错误时返回一个负的错误码。
说明

MPI_Init 可能会修改 argcargv 的值。在 MPI_Init 调用后,argcargv 应被视为未定义,除非它们在 MPI_Init 内部没有被改变。

MPI_Finalize

MPI_Finalize 用于关闭 MPI 环境,释放由 MPI 库分配的所有资源,并确保所有未完成的通信请求都已完成

函数原型
int MPI_Finalize();
返回值
  • 成功时返回 MPI_SUCCESS
  • 发生错误时返回一个负的错误码。
说明

MPI_Finalize 被调用之后,除了 MPI_Get_processor_nameMPI_Finalized 之外,不应再调用任何其他 MPI 函数。一旦 MPI_Finalize 被调用,MPI 环境就无法再次初始化。

MPI_Comm_size

MPI_Comm_size 用于查询给定通信子中的进程数量。

函数原型
int MPI_Comm_size(MPI_Comm comm, int *size);
参数
  • comm:要查询的通信子。
  • size:一个指向整数的指针,用于存储通信子中的进程数量。
返回值
  • 成功时返回 MPI_SUCCESS
  • 发生错误时返回一个负的错误码。

MPI_Comm_rank

MPI_Comm_rank 用于查询调用进程在给定通信子中的标识符(rank)。

函数原型
int MPI_Comm_rank(MPI_Comm comm, int *rank);
参数
  • comm:要查询的通信子。
  • rank:一个指向整数的指针,用于存储调用进程在通信子中的标识符。
返回值
  • 成功时返回 MPI_SUCCESS
  • 发生错误时返回一个负的错误码。

MPI_Send

MPI_Send 用于将数据从一个进程发送到另一个进程。其函数原型如下:

int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm);
参数
  • buf:指向要发送的数据缓冲区的指针。
  • count:要发送的数据项数量。
  • datatype:每个数据项的类型(例如 MPI_INT 对应整型)。
  • dest:目标进程的 rank(在通信子中的标识符)。
  • tag:消息标签,用于区分不同类型的消息。
  • comm:通信子,定义了发送和接收进程之间的上下文。
返回值
  • 成功时返回 MPI_SUCCESS
  • 如果出现错误,则返回一个负的错误码

MPI_Recv

MPI_Recv 用于从另一个进程接收数据。其函数原型如下:

int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status);
参数
  • buf:指向用于存放接收到的数据的缓冲区的指针。
  • count:接收缓冲区能够容纳的数据项的最大数量。
  • datatype:每个数据项的类型。
  • source:发送进程的 rank。如果设置为 MPI_ANY_SOURCE,则可以从任意源接收消息。
  • tag:期望的消息标签。如果设置为 MPI_ANY_TAG,则可以接收任何标签的消息。
  • comm:通信子。
  • status:一个指向 MPI_Status 结构体的指针,用来提供关于接收到的消息的信息(如源进程rank和实际接收到的数据项数量)。如果不关心这些信息,可以传递 MPI_STATUS_IGNORE
返回值
  • 成功时返回 MPI_SUCCESS
  • 如果出现错误,则返回一个负的错误码。

刚开始不用太在意细节,知道大概怎么用,什么效果即可。

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

int main(int argc, char** argv) { 

  /*
  // 初始化
  MPI_Init(NULL, NULL);

  int rank;
  // 获取进程标识,但是PID(进程ID)是运行态概念,而MPI进程则是个静态概念,所以MPI把标识抽象为0~np-1
  // MPI_COMM_WORLD表示默认通信域
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  long long sum = 0;
  for (long long i = 0; i < 10000000000; i++) sum += i;

  int size;
  // 获取通信域中包含多少进程
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  printf("I'm rank #%d total %d :Hello world! %lld\n",rank,size,sum);


  // 结束
  MPI_Finalize();
  */

  // ---------------通信----------------

  MPI_Init(NULL, NULL);
  int tag = 10086;
  int count = 1;
  MPI_Status status;
  int rank;

  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  if (rank == 0) {
    int* sendbuff = (int*)malloc(sizeof(int) * count);
    sendbuff[0] = 1;
    MPI_Send(sendbuff, count, MPI_INT, 1, tag, MPI_COMM_WORLD);
    printf("I'm rank #%d, sendbuff[0] = %d\n", rank, sendbuff[0]);
  } else if (rank == 1) {
    int* recvbuff = (int*)malloc(sizeof(int) * count);
    recvbuff[0] = 200;
    printf("I'm rank #%d , before recv, recvbuff[0] = %d\n", rank, recvbuff[0]);
    MPI_Recv(recvbuff, count, MPI_INT, 0, tag, MPI_COMM_WORLD, &status);
    printf("I'm rank #%d , after recv, recvbuff[0] = %d\n", rank, recvbuff[0]);

  }
  MPI_Finalize();

  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值