首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MPI编程入门详解

MPI编程入门详解

作者头像
狼啸风云
修改2022-09-03 19:11:37
6.3K0
修改2022-09-03 19:11:37
举报

MPI简介

说到并行计算,我们有一个不可绕开的话题——MPI编程。MPI是一个跨语言的通讯协议,用于编写并行计算机。支持点对点和广播。MPI是一个信息传递应用程序接口,包括协议和和语义说明,他们指明其如何在各种实现中发挥其特性。MPI的目标是高性能,大规模性,和可移植性。MPI在今天仍为高性能计算的主要模型。与OpenMP并行程序不同,MPI是一种基于信息传递的并行编程技术。消息传递接口是一种编程接口标准,而不是一种具体的编程语言。简而言之,MPI标准定义了一组具有可移植性的编程接口。

MPI基本函数

MPI调用借口的总数虽然庞大, 但根据实际编写MPI的经验, 常用的MPI调用的个数确什么有限。 下面是6个最基本的MPI函数。 1.  MPI_Init(…); 2.  MPI_Comm_size(…); 3.  MPI_Comm_rank(…); 4.  MPI_Send(…); 5.  MPI_Recv(…); 6.  MPI_Finalize(); 我们在此通过一个简单的例子来说明这6个MPI函数的基本用处。

函数介绍

1. int MPI_Init (int* argc ,char** argv[] )

该函数通常应该是第一个被调用的MPI函数用于并行环境初始化,其后面的代码到 MPI_Finalize()函数之前的代码在每个进程中都会被执行一次。 –  除MPI_Initialized()外, 其余所有的MPI函数应该在其后被调用。 –  MPI系统将通过argc,argv得到命令行参数(也就是说main函数必须带参数,否则会出错)。

2. int MPI_Finalize (void)

–  退出MPI系统, 所有进程正常退出都必须调用。 表明并行代码的结束,结束除主进程外其它进程。 –  串行代码仍可在主进程(rank = 0)上运行, 但不能再有MPI函数(包括MPI_Init())。

3. int MPI_Comm_size (MPI_Comm comm ,int* size )

–  获得进程个数 size。 –  指定一个通信子,也指定了一组共享该空间的进程, 这些进程组成该通信子的group(组)。 –  获得通信子comm中规定的group包含的进程的数量。

4. int MPI_Comm_rank (MPI_Comm comm ,int* rank)

–  得到本进程在通信空间中的rank值,即在组中的逻辑编号(该 rank值为0到p-1间的整数,相当于进程的ID。)

5. int MPI_Send( void *buff, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)

–void *buff:你要发送的变量。 –int count:你发送的消息的个数(注意:不是长度,例如你要发送一个int整数,这里就填写1,如要是发送“hello”字符串,这里就填写6(C语言中字符串未有一个结束符,需要多一位))。 –MPI_Datatype datatype:你要发送的数据类型,这里需要用MPI定义的数据类型,可在网上找到,在此不再罗列。 –int dest:目的地进程号,你要发送给哪个进程,就填写目的进程的进程号。 –int tag:消息标签,接收方需要有相同的消息标签才能接收该消息。 –MPI_Comm comm:通讯域。表示你要向哪个组发送消息。

参数说明

6. int MPI_Recv( void *buff, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)

–void *buff:你接收到的消息要保存到哪个变量里。 –int count:你接收消息的消息的个数(注意:不是长度,例如你要发送一个int整数,这里就填写1,如要是发送“hello”字符串,这里就填写6(C语言中字符串未有一个结束符,需要多一位))。它是接收数据长度的上界. 具体接收到的数据长度可通过调用MPI_Get_count 函数得到。 –MPI_Datatype datatype:你要接收的数据类型,这里需要用MPI定义的数据类型,可在网上找到,在此不再罗列。 –int dest:接收端进程号,你要需要哪个进程接收消息就填写接收进程的进程号。 –int tag:消息标签,需要与发送方的tag值相同的消息标签才能接收该消息。 –MPI_Comm comm:通讯域。 –MPI_Status *status:消息状态。接收函数返回时,将在这个参数指示的变量中存放实际接收消息的状态信息,包括消息的源进程标识,消息标签,包含的数据项个数等。

示例

基本函数都已经介绍完,现在我们来用一个示例来加强对这些基本函数的理解。

#include <stdio.h>
#include <string.h>
#include "mpi.h"
void main(int argc, char* argv[])
{
    int numprocs, myid, source;
    MPI_Status status;
    char message[100];
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    if (myid != 0) {  //非0号进程发送消息
        strcpy(message, "Hello World!");
        MPI_Send(message, strlen(message) + 1, MPI_CHAR, 0, 99,
            MPI_COMM_WORLD);
    }
    else {   // myid == 0,即0号进程接收消息
        for (source = 1; source < numprocs; source++) {
            MPI_Recv(message, 100, MPI_CHAR, source, 99,
                MPI_COMM_WORLD, &status);
            printf("接收到第%d号进程发送的消息:%s\n", source, message);
        }
    }
    MPI_Finalize();
} /* end main */

运行结果如下图所示

可以看到,当笔者开启四线程运行时,1-3号进程发送消息,0号进程接收到消息并打印;当笔者开启八线程运行时,1-7号进程发送消息,0号进程接收到消息并打印。

本文使用的是标准阻塞接收发送的方式。消息传递是MPI的特性,也是我们学习的难点。这我们学习MPI必须掌握的。

消息发送与接收函数的参数的一些重要说明。

1.MPI标识一条消息的信息包含四个域:

  1. –  源:发送进程隐式确定,进程rank值唯一标识.
  2. –  目的:Send函数参数确定.
  3. –  Tag:Send函数参数确定, (0,UB) 232-1.
  4. –  通信子:缺省MPI_COMM_WORLD
  5. •  Group:有限/N, 有序/Rank [0,1,2,…N-1]
  6. •  Contex:Super_tag,用于标识该通讯空间.

2. buffer的使用

  1. buffer必须至少可以容纳count个由datatype指明类型的数据. 如果接收buf太小, 将导致溢出、 出错

3. 消息匹配

  1. –  参数匹配source,tag,comm/dest,tag,comm.
  2. –  Source == MPI_ANY_SOURCE: 接收任意处理器来的数据(任意消息来源).
  3. –  Tag == MPI_ANY_TAG: 匹配任意tag值的消息(任意tag消息).

4. 在阻塞式消息传送中不允许Source == dest,否则会导致死锁.

5. 消息传送被限制在同一个通信域内。

6. 在send函数中必须指定唯一的接收者。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-01-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MPI简介
  • MPI基本函数
  • 函数介绍
    • 1. int MPI_Init (int* argc ,char** argv[] )
      • 2. int MPI_Finalize (void)
        • 3. int MPI_Comm_size (MPI_Comm comm ,int* size )
          • 4. int MPI_Comm_rank (MPI_Comm comm ,int* rank)
            • 5. int MPI_Send( void *buff, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
              • 6. int MPI_Recv( void *buff, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
              • 示例
              • 消息发送与接收函数的参数的一些重要说明。
                • 1.MPI标识一条消息的信息包含四个域:
                  • 2. buffer的使用
                    • 3. 消息匹配
                      • 4. 在阻塞式消息传送中不允许Source == dest,否则会导致死锁.
                        • 5. 消息传送被限制在同一个通信域内。
                          • 6. 在send函数中必须指定唯一的接收者。
                          相关产品与服务
                          GPU 云服务器
                          GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档