OpenMPI 学习笔记(三)点对点通信

一、原理

所谓的点对点通信发生在两个过程之间:发射器和接收器(或接收器)。
发射器和接收器通过它们在通信器中的等级来识别。


发送的消息包括:

  1. 沟通者(必须包含两个进程)
  2. 发送者的等级,
  3. 接收者的等级,
  4. 消息的标签(标识符)。
  5. 报告的数据类型必须指定。
  6. 有几种传输模式。

二、例子

int MPI_Ssend(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);

comm : 沟通器

tag : 信息标签

dest/source : 在该沟通器中的发送者和接受者的等级号

datatype : 所发送的数据的类型

count :发送和接受的数据数量

buf : 发送/接收的数据的开始地址

// intro/send-receive.c

#include <mpi.h> 
#include <stdio.h>
int main(int argc, char** argv) {

    MPI_Init(&argc, &argv);

    int wrank; MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
    int witness = 0; if (wrank==2)
    {
        int modifier = 1;
        MPI_Ssend(&modifier, 1, MPI_INT, 3, 28, MPI_COMM_WORLD);
    }
    else if (wrank==3)
        MPI_Recv(&witness, 1, MPI_INT, 2, 28, MPI_COMM_WORLD,
                MPI_STATUS_IGNORE);
    printf("Rang %d, witness %d.\n", wrank, witness); 

    MPI_Finalize();
    return 0;
                                              
}                

上面执行的是:进程2发给进程3一个int型数字 :1

在控制台测试:

$ mpirun -n 4 source

Rang 1, witness 0.

Rang 0, witness 0.

Rang 2, witness 0.

Rang 3, witness 1.

 

上面演示的是传递一个值,下面我们看传递多个值的情况:

// intro/send-receive.c
int witness[] = {0, 0};  
if (wrank==2)
{
    int modifier[] = {1, 1};
    MPI_Ssend(modifier, 2, MPI_INT, 3, 28, MPI_COMM_WORLD);
}
else if (wrank==3)
    MPI_Recv(witness, 2, MPI_INT, 2, 28, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                 

对于所有通信,须指定通信类型(MPI有很多种通信类型),而且发送者和接受者的类型应当配套使用:

MPI_Ssend的标签必须与MPI_Recv的标签匹配,否则通信失败。

数据传输是用一个简单的字节完成的(类型中没有数据)。

由程序员来验证发送和接收的类型是相同的,或者至少它们是兼容的(参见示例框架153和158)

 

⚠️注

如果发送的字节数等于接收的字节数,通信将成功。例如,可以发送一个包含两个int的数组,并接收一个long或者一个double。

 

三、有关标签的详细信息

标记必须是介于0和系统相关值之间的整数,系统相关值由以下程序获取。该最大值总是≥32767。

// tag.c
#include <mpi.h> 
#include <stdio.h>

int main(int argc, char** argv) {
MPI_Init(
&argc, &argv); int flag; int* max_tag;

   MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB,
&max_tag, &flag); printf("Maximum tag : %d.\n", *max_tag); MPI_Finalize(); return 0; }

多个进程重复使用相同的标签不是一个问题:无论通信的模式如何,接收顺序与发送顺序相同。

 

待解决:

À la réception d'un message, le rang de l'émetteur et l'étiquette peuvent être des 􏰂 jokers 􏰃, respectivement MPI_ANY_SOURCE etMPI_ANY_TAG.

收到消息后,发送方的等级和标签分别可以是“jokers”MPI_ANY_SOURCE和MPI_ANY_TAG。

 

四、基本数据类型

      所有MPI_ *类型的大小均为8个字节。

 

⚠️补充说明:

只有收到指定标签的全部消息时,接收过程才会退出对MPI_Recv的调用。
发送过程的行为更加复杂(参见后面讲解)。
MPI_STATUS_IGNORE是一个可以用来代替状态变量的预定义常量。
可以创建和传达更复杂的数据结构。

 

posted @ 2018-04-16 18:17  yanwenliqjl  阅读(1491)  评论(0编辑  收藏  举报