MPI:使用核心还是处理器?

29

嗨,我对MPI还不太熟悉,希望您能耐心解答。 :)

假设我有一个名为foo.c的MPI程序,并使用以下命令运行可执行文件:

mpirun -np 3 ./foo

现在,这意味着该程序将使用3个处理器(每个处理器1个进程)并行运行。但由于今天的大多数处理器具有多个核心(例如每个处理器2个核心),这是否意味着该程序将在3个核心或3个处理器上运行?

这可能与我对核心和处理器之间区别的理解不足有关,因此如果您能再解释一下就更好了。

谢谢。


1
如果在Linux机器上运行cat /proc/cpuinfo命令,您会发现每个超线程都被计算为一个处理器,这恰好与MPI对“处理器”的使用一致。 - Hackless
6个回答

41

mpirun将在机器上执行多个"进程"。这些进程执行的CPU或核心取决于操作系统。

在具有M个核心的N个CPU的机器上,您可以运行N*M个进程。

但是,通常情况下:

  • 如果有多个核心,则每个进程将在不同的核心上运行
  • 如果您请求的进程数超过了可用的核心* CPU,所有内容都将运行,但效率会降低(是的,您可以在单个CPU单个内核的机器上运行多进程作业...)
  • 如果您使用排队系统或预配置的MPI系统,其中存在远程机器列表,则分配将分布在远程机器上。

(根据MPI实现的不同,可能有一些选项来强制使用特定的CPU或核心,但您不需要担心这个问题)。


谢谢你的回答,它也帮助了我! - Vappor Washmade

5

过程到核心和处理器的分配由操作系统和MPI实现处理。在桌面上运行时,操作系统通常会将每个进程放在不同的核心上,在运行时可能重新分配进程。在较大的系统中,如超级计算机或集群系统,则由资源管理器(例如SLURM)处理分配。无论如何,一个或多个进程将被分配给每个核心。

关于硬件,一个核心一次只能运行一个进程。超线程等技术允许多个进程共享单个核心的资源。有些情况下,每个核心有两个或更多进程是最优的。例如,如果一个进程正在进行大量文件I/O,另一个进程可以顶替它并在第一个进程在读写上挂起时进行计算。

简而言之,给MPI提供要执行的进程数量。这些进程的分配将对用户透明处理。您使用的进程数应由应用程序的要求(2的幂次方、要读取的文件数)、可用的核心数以及应用程序所需的每个核心的最佳进程数来确定。


4

mpirun命令使用主机列表。如果不指定,则可能会使用“localhost”并在那里运行所有进程。如果您运行3个进程,并且您有一台4核机器,那么您可能会获得良好的加速,因为操作系统通常会将它们放在不同的核心上。如果您只有两个核心,则一个核心将获得两个进程。

前面的说法并非完全正确,因为操作系统允许移动进程,因此您可能希望使用numactl将它们绑定到一个核心。

如果您在多节点集群上,则良好设置的mpi将生成一个主机文件,在该文件中,每个节点出现的次数与其核心数相同。因此,在具有每个节点8个核心的4节点集群上,您可以请求最多32个进程,并期望接近完美的加速。(当然,如果您的代码和算法允许这样做。)在该集群上请求9个进程可能会将8个进程放在一个节点上,第9个进程放在另一个节点上,这对性能来说显然不是很好。您希望您的集群软件带有一个比这更好地分配进程的mpirun。


4
操作系统的调度器会尝试在多核系统中为并行应用程序的进程分配单独的核心,或者在多处理器系统中分配不同的处理器。
有趣的情况是多核多CPU系统。同样,您可以让操作系统调度器为您完成此任务,或者强制将进程的(逻辑/物理)内核亲和力绑定到特定的内核。

2

从MPI作业的性能角度来看,有一些明确的规则: 1)如果您的代码是纯MPI代码(未使用openMP调整的BLAS),请关闭超线程并将每个节点作业的任务数设置为节点的核心数。 2)如果您的代码是MPI + openMP,则可以将PPN(每个节点的进程数)设置为节点的核心数,并将OMP_NUM_THEADS设置为2(如果每个核心有两个硬件线程)。 3)如果您的代码是MPI + openMP且您的集群非常庞大,则可以将PPN(每个节点的进程数)设置为1,将OMP_NUM_THEADS设置为逻辑CPU数以节省通信开销。


0
为了提供一个有用的框架,我建议按以下层次结构来考虑:
  • 一个主板可以容纳一个或多个芯片/晶元;
    • 一个芯片/晶元可以包含一个或多个核心(独立的CPU);
      • CPU可以同时处理一个或多个线程(我知道的多线程由两个线程组成)

早期,你通常有一个主板,一个芯片,一个CPU运行一个线程。一次只能处理一个进程,参与处理的硬件集被称为“处理器”。软件(要运行的任务)和硬件(运行任务的设备)之间存在一对一的映射关系。

进程(Process)是一个软件概念。'线程(Thread)'在并行计算上下文中,简单地说,是对'进程(Process)'的规范。现在,处理器(Processor)既可以指物理设备,也可以指其扩展的处理能力(再次多线程,这当然是一种技术实现)。例如,您可以拥有主板上带有两个芯片的机器,每个芯片有四个核心/CPU,并且每个核心/CPU同时运行两个线程。然后,您将能够运行2x4x2=16个进程(当然不会超额使用资源)。

您引用的MPI语法涉及到进程(Processes)(选项np),或者如果您喜欢,就是线程(Threads)。mpirun手册的描述部分甚至将进程称为“插槽”(例如,请参阅hostfile的规格说明)。

插槽(Slots)表示节点上可能执行的进程数量。

这种用法听起来像是那个时代硬件单位和软件单位之间密切对应的遗产。'插槽(Slot)'最初是一种材料/硬件特征,类似于'插座(Socket)'这个术语在某些情况下经历了类似的语义变化。

我确实对你的困惑感到同情。如果你是Linux用户,你可以通过可视化cat /proc/cpuinfo报告来了解这些行,它们指的是四个处理器中的一个名为“2”的处理器:

processor   : 2
...
physical id : 0
siblings    : 4
core id     : 2
cpu cores   : 4

他们说,在这台机器上我只得到了一个芯片(因为“物理ID”在整个列表中只有一个值,被省略),这个芯片有4个“CPU核心”,并且这个芯片正在运行四个兄弟(4个线程,因此没有多线程)。在这种情况下,有4个处理元素和4个CPU核心。
在上面的多线程示例中,您将看到16个处理器的列表,2个“物理ID”(芯片)的值,“CPU核心”等于4(每个芯片),而“siblings”等于8(每个芯片),因为该芯片启用了多线程。在这种情况下,处理器数量是核心数量的四倍。
因此,在这个扩展的上下文中,“处理器”表示机器处理“进程”的能力,这就是MPI和您想要使用的,无论可以启用多少个核心。您只需要获得这些处理能力来自哪里的概述。
另一个有用的Linux命令是lscpu
...
CPU(s):                4
On-line CPU(s) list:   0-3
Thread(s) per core:    1
Core(s) per socket:    4
Socket(s):             1
...

'Socket' 的确是主板上芯片插座的物理连接,因此它确实是芯片的别名。但在这里并没有多线程。

我非常感谢在这篇https://unix.stackexchange.com/q/146051/132913中的讨论。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接