这是一个不适定的问题,因为等级的最大数量取决于很多因素,很难给出简短和/或完整的答案。
首先,MPI_Comm_size()
和MPI_Comm_rank()
are的输出参数,int
在当今大多数平台上都是 32 位的,因此硬性上限为 20 亿 (2 31 -1) 列。
然后是特定 MPI 实现所施加的限制。不幸的是,MPI 没有指定在 MPI 作业中获得最大等级数的方法,您必须查阅实现的文档,但假设大多数使用int
s 用于内部索引,因此限制可能相同 - 20 亿等级。
然后是 MPI 库如何实现 MPI 等级的问题。Linux 上大多数现成的 MPI 都是操作系统进程,因此我们需要研究可以同时运行多少个进程。
首先,存在 Linux 内核可以处理的最大进程数。默认情况下,进程 ID (PID) 在达到 中指定的值时回绕/proc/sys/kernel/pid_max
,系统启动时为 32768。这是 32 位 Linux 的上限,也是 64 位 Linux 的默认限制(为了向后兼容),但在 64 位 Linux 上最多可以更改为 2 22。用户进程的 PID 从 300 开始,除了非常特殊的第一个用户进程(古老的init
)始终为 1。因此,您最多可以同时运行2 22init
-300 个进程,大约 420 万,但通常更少因为内核线程也可以吃掉那个 PID 空间。
然后是该ulimit
机制施加的用户限制。ulimit -u
为用户设置或获取运行进程的限制。Ubuntu 18.04 上的默认值为 483294,这也是该限制的最大可能值(即硬限制)。由于 MPI 作业通常在相同的用户名下运行,因此此限制限制了可以拥有的等级数。
典型的 MPI 实现带有一个特殊的启动器进程,因此您无法在 64 位 Ubuntu 18.04 上启动具有超过 483293 个等级的 MPI 作业。但同样,这只是一个上限。还有更多。
每个操作系统进程都有自己的虚拟地址空间页表和相应的内核结构,并且这些结构会消耗内存。最重要的是进程完成的任何额外内存分配。您问题中的最小 MPI 程序添加了一个调用sleep(3)
,以便ps
在程序退出之前有时间运行命令,在 64 位 Ubuntu 18.04 上使用 Open MPI 编译并去除调试符号,具有常驻集大小( RSS)为每列 12 MiB。这mpiexec
启动器有更多,它的内存使用量随着 MPI 等级的数量而增长,但让我们忽略这一点。也忽略内核内存使用以及典型 Linux 系统上还有其他进程的事实,您不能运行超过(16 GiB + 交换量)/ 12 MiB 的进程。交换大小的范围通常从根本没有交换到 RAM 大小的两倍,尽管它实际上可以是任何东西。如果没有交换,您将被限制为 1364 个等级。使用两倍于 RAM 大小的交换大小,您可以拥有 4095 个等级。为简单起见,我们假设前一种情况,即没有交换,因此限制为 1364 个等级。
这个简单的程序不做任何计算密集型的事情。如果它实际上是在计算某些东西,那么这 1364 个等级将竞争 12 个逻辑 CPU,每个本地 CPU 有 114 个进程,这有点荒谬。因此,如果有通过利用超线程来隐藏内存延迟的良好选项,则更明智的限制是 12,或者甚至只有 6,如果程序正在运行一些非常紧凑的循环,并且不会不断到达核心私有之外的数据缓存。
因此,如您所见,您关于有效范围的问题是不恰当的。至于在 12 个逻辑 CPU 上运行总共 24 个 MPI 等级,只需输出即可"Hello world"
。
至于开始 24 秩 MPI 作业时的值rank
和size
可能是什么,答案在于 MPI 作业的大小MPI_COMM_WORLD
是全局固定的,并且是最初请求的 MPI 等级数的大小-np
参数,而实际排名数从0
到变化size - 1
。