跳转到内容

消息传递接口/MPI 函数参考

来自维基教科书,开放书籍,开放世界
(重定向自 MPI 函数参考)

此页面列出了 MPI 中使用的函数的简要说明。


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

这将 buf 的内容发送到秩为 dest 的目标,而接收端则调用 MPI_Recv


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

这将 buf 填充来自秩为 source 的源的数据,而发送端则调用 MPI_Send


int MPI_Bcast ( void *buffer, int count, MPI_Datatype datatype, int root, 
                MPI_Comm comm )

这将 buffer 中的内容在 root 上发送到所有其他进程。因此,之后 buffer 的前 count 个元素在所有节点上都相同。 [1]

MPI_Bcast 的性能可能在 之间。 [2][3]

MPI 2.0 连接命令

[编辑 | 编辑源代码]
int MPI_Open_port(MPI_Info info, char *port_name)

这将创建一个端口,其他进程可以连接到该端口。作为 port_name 字符串传递的缓冲区必须至少 MPI_MAX_PORT_NAME 长,并且将包含一个唯一的标识符,其他进程需要知道该标识符才能连接。


int MPI_Comm_accept(char *port_name, MPI_Info info, int root, MPI_Comm comm, 
                    MPI_Comm *newcomm)

在调用 MPI_Open_port() 后,此函数将等待连接。


int MPI_Comm_connect(char *port_name, MPI_Info info, int root, MPI_Comm comm, 
                      MPI_Comm *newcomm)

这将打开到另一个进程的连接,该进程正在 MPI_Comm_accept() 上等待。port_name 参数必须与另一个进程的 port_name 相同,该 port_name 是从 MPI_Open_port 返回的。

以下函数通过应用简单函数(例如求和)将跨处理器的数组数据归约为一个或多个处理器上的标量。


int MPI_Scan ( void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
               MPI_Op op, MPI_Comm comm )

参见 [4].


int MPI_Allreduce ( void *sendbuf, void *recvbuf, int count, 
                    MPI_Datatype datatype, MPI_Op op, MPI_Comm comm )

这将在所有节点上对每个节点的 sendbuf 执行由 MPI_Op 指定的操作。例如,如果节点 0 在其 sendbuf 中分别有 {0, 1, 2},而节点 1 有 {3, 4, 5},并且如果两者都调用了 MPI_Allreduce(sendbuf, foo, 3, MPI_INT, MPI_SUM, world),则两个节点上指向 foo 的缓冲区的内容将是

{0+3, 1+4, 2+5} = {3, 5, 7}


对于 *P* 个进程的性能: [5]


int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm);

MPI_Comm_split() 在每个进程中创建一个新的通信器。生成的通信器对提供相同 color 参数的进程是通用的。进程可以通过提供 MPI_UNDEFINED 作为 color 来选择不获取通信器,这将为该进程生成 MPI_COMM_NULL

例如,以下代码将 MPI_COMM_WORLD 拆分为三个通信器,分别“着色”为 0、1 和 2。

#include<iostream>
#include<mpi.h>

using namespace std;

int main(int argc, char** argv) {
  MPI_Init(&argc, &argv);
  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm comm;
  MPI_Comm_split(MPI_COMM_WORLD, rank % 3, -rank*2, &comm); // The keys need not be positive or contiguous.
  int rank2;
  MPI_Comm_rank(comm, &rank2);
  cout << "My rank was " << rank << " now " << rank2 << " color: " << rank % 3 << "\n";
  MPI_Finalize();
}

使用八个进程运行,这将输出以下内容(以不确定的顺序)

My rank was 0 now 2 color: 0
My rank was 8 now 2 color: 1
My rank was 8 now 1 color: 2
My rank was 3 now 1 color: 0
My rank was 4 now 1 color: 1
My rank was 5 now 0 color: 2
My rank was 6 now 0 color: 0
My rank was 7 now 0 color: 1
My rank was 8 now 0 color: 1

非阻塞异步通信

[编辑 | 编辑源代码]

以下函数协同工作,以允许进程之间进行非阻塞异步通信。 [6] 一个进程发送,而另一个进程接收。发送方必须在擦除缓冲区之前检查操作是否已完成。MPI_Wait() 是一个阻塞等待,而 MPI_Test 是非阻塞的。

MPI_Isend()MPI_Irecv() 调用不必按顺序进行。也就是说,进程 42 可以调用 MPI_Irecv() 三次来开始从进程 37、38 和 39 接收,它们可以随时发送。


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

---

int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request recvtag, MPI_Comm comm, MPI_Status *status);

int MPI_Wait(MPI_Request *request, MPI_Status *status);

int MPI_Test(MPI_Request  *request, int* flag, MPI_Status* status);


示例代码

#include<iostream>
#include<mpi.h>

using namespace std;

int main(int argc, char** argv) {
  MPI_Init(&argc, &argv);
  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm comm;

  int sources[] = {3,4,5};
  int dest = 1;
  int tag =42;
  if (rank == sources[0] || rank == sources[1] || rank == sources[2]) {
    double x[] = { 1*rank, 2*rank, 3*rank};
    MPI_Request r;
    MPI_Isend(x, 3, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD, &r);
    cout << "Process " << rank << " waiting...\n";
    MPI_Status status;
    MPI_Wait(&r, &status);
    cout << "Process " << rank << " sent\n";
  } else if(rank == dest) {
    double x[3][3];
    MPI_Request r[3];
    for (int i = 0; i !=3; ++i) {
      MPI_Irecv(x[i], 3, MPI_DOUBLE, sources[i], tag, MPI_COMM_WORLD, &r[i]);
      cout << "Process " << rank << " waiting for " << sources[i] << " on recv.\
\n";
    }
    for (int i = 0; i !=3; ++i) {
      MPI_Status status;
      MPI_Wait(&r[i], &status);
    cout << "Process " << rank << " got " << x[i][0] << " " << x[i][1] << " " <\
< x[i][2] << ".\n";
    }
  }

  MPI_Finalize();
}

[其他函数]

[编辑 | 编辑源代码]
int MPI_Init(int *argc, char ***argv);
int MPI_Finalize(void);
int MPI_Comm_rank(MPI_Comm comm, int *rank);
int MPI_Comm_size(MPI_Comm comm, int *size);
int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count);
int MPI_Type_extent(MPI_Datatype datatype, MPI_Aint *extent);
int MPI_Type_struct(int count, int *array_of_blocklengths, MPI_Aint *array_of_displacements, MPI_Datatype *array_of_types, MPI_Datatype *newtype);
int MPI_Scatter(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvcount, int root, MPI_Comm comm);  Performance potential: As good as log_2 (N) as bad as N. http://www.pdc.kth.se/training/Talks/MPI/Collective.I/less.html#perf_scatter_image
int MPI_Gather(void* sendbuf, int sendcount, MPI_Datatype sendype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm); --  [7]
  • request);
int MPI_Sendrecv(void* sendbuf, int sendcount, MPI_Datatype datatype, int dest, int sendtag, void* recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status);
int MPI_Sendrecv_replace(void* buf, int count, MPI_Datatype datatype, int dest, int sendtag, int source, int  int MPI_Request_free(MPI_Request *request);
int MPI_Group_rank(MPI_Group group, int *rank);
int MPI_Group_size(MPI_Group group, int *size);
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group);
int MPI_Group_free(MPI_Group *group);
int MPI_Group_incl(MPI_Group *group, int n, int *ranks, MPI_Group *newgroup);
int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newgroup);
int MPI_Wtime(void);
int MPI_Get_processor_name(char *name, int *resultlen);
[编辑 | 编辑源代码]
华夏公益教科书