使用 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()
是一个集体调用。
我发现了一个名为 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()
是一个集体调用。