使用 MPI_COMM_SELF

Use of MPI_COMM_SELF

我发现了一个名为 MPI_COMM_SELF 的 MPI 通信器。问题是,我不知道,什么时候有用。在我看来,只有每个进程 "thinks" 都以 root 身份存在。

你能解释一下 MPI_COMM_SELF 是如何工作的吗?它在哪些情况下有用?

我找到了 this 幻灯片放映,但那里只是简单地提到了通信器。


我试过这个 "Hello, world" 示例,所有进程都返回 0 作为它们的 PID。

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

int main() {
    MPI_Init(NULL, NULL);

    int world_rank;
    MPI_Comm_rank(MPI_COMM_SELF, &world_rank);

    printf("Hello, my PID is %d!\n",
            world_rank);

    MPI_Finalize();
    return 0;
}

一个 MPI 通信器是两条信息:进程的集合和该集合的上下文。默认的通信器是 MPI_COMM_WORLD——每个进程——和 MPI_COMM_SELF——只有一个进程。

您可以使用所有、一个或部分进程创建更多通信器。

为什么上下文很重要?想想图书馆。使用 MPI 的库可能会与该库的客户端发生冲突,但库会复制通信器,从而创建一个库可以通信的上下文,而无需担心客户端在做什么。

MPI_COMM_SELF 是单个进程。如果调用集体例程,通信器中的所有进程都必须参与。

MPI_COMM_SELF 对 MPI-IO 例程特别有用,但前提是您需要 "file per process"。如果您正在与多个 MPI 进程共享文件(您可能应该这样做),请使用包含这些 MPI 进程的通信器。

除了IO相关的使用MPI_COMM_SELF,MPI标准中还有两个描述

MPI_COMM_SELF 的一个特殊用途是在 MPI 库完成期间调用用户函数,这与 C 中的 atexit() 机制非常相似。事实上,不能可靠地使用 atexit() MPI 程序中的机制,因为 MPI 实现不需要从 MPI_Finalize() return 除了等级 0,因此需要另一种机制(此外,Fortran 没有等价于 atexit())。幸运的是,MPI 提供了一种缓存机制,允许将任意属性可移植关联到一些 MPI 对象,即通信器、windows 和数据类型,这在编写可移植库时主要有用。每个属性都有一组复制和删除回调,每次发生特定事件时都会调用这些回调,例如,当属性因复制通信器而被复制时。该标准不保证所有 MPI 对象在 MPI_Finalize() 期间被销毁的顺序,但它保证 MPI_COMM_SELF 是第一个被销毁的对象。因此,将带有删除回调的属性附加到 MPI_COMM_SELF 将在调用 MPI_Finalize().

后立即触发回调

MPI_COMM_SELF 的另一个用途是 MPI 的 client/server 机制。如果您有一个 MPI 作业并希望其中一个队列从单独的 MPI 作业接收客户端连接,则必须使用 MPI_COMM_SELF,因为 MPI_Comm_accept() 是一个集体调用。