嗨,我对MPI还不太熟悉,希望您能耐心解答。 :)
假设我有一个名为foo.c的MPI程序,并使用以下命令运行可执行文件:
mpirun -np 3 ./foo
现在,这意味着该程序将使用3个处理器(每个处理器1个进程)并行运行。但由于今天的大多数处理器具有多个核心(例如每个处理器2个核心),这是否意味着该程序将在3个核心或3个处理器上运行?
这可能与我对核心和处理器之间区别的理解不足有关,因此如果您能再解释一下就更好了。
谢谢。
嗨,我对MPI还不太熟悉,希望您能耐心解答。 :)
假设我有一个名为foo.c的MPI程序,并使用以下命令运行可执行文件:
mpirun -np 3 ./foo
现在,这意味着该程序将使用3个处理器(每个处理器1个进程)并行运行。但由于今天的大多数处理器具有多个核心(例如每个处理器2个核心),这是否意味着该程序将在3个核心或3个处理器上运行?
这可能与我对核心和处理器之间区别的理解不足有关,因此如果您能再解释一下就更好了。
谢谢。
mpirun将在机器上执行多个"进程"。这些进程执行的CPU或核心取决于操作系统。
在具有M个核心的N个CPU的机器上,您可以运行N*M个进程。
但是,通常情况下:
(根据MPI实现的不同,可能有一些选项来强制使用特定的CPU或核心,但您不需要担心这个问题)。
过程到核心和处理器的分配由操作系统和MPI实现处理。在桌面上运行时,操作系统通常会将每个进程放在不同的核心上,在运行时可能重新分配进程。在较大的系统中,如超级计算机或集群系统,则由资源管理器(例如SLURM)处理分配。无论如何,一个或多个进程将被分配给每个核心。
关于硬件,一个核心一次只能运行一个进程。超线程等技术允许多个进程共享单个核心的资源。有些情况下,每个核心有两个或更多进程是最优的。例如,如果一个进程正在进行大量文件I/O,另一个进程可以顶替它并在第一个进程在读写上挂起时进行计算。
简而言之,给MPI提供要执行的进程数量。这些进程的分配将对用户透明处理。您使用的进程数应由应用程序的要求(2的幂次方、要读取的文件数)、可用的核心数以及应用程序所需的每个核心的最佳进程数来确定。
mpirun命令使用主机列表。如果不指定,则可能会使用“localhost”并在那里运行所有进程。如果您运行3个进程,并且您有一台4核机器,那么您可能会获得良好的加速,因为操作系统通常会将它们放在不同的核心上。如果您只有两个核心,则一个核心将获得两个进程。
前面的说法并非完全正确,因为操作系统允许移动进程,因此您可能希望使用numactl
将它们绑定到一个核心。
如果您在多节点集群上,则良好设置的mpi将生成一个主机文件,在该文件中,每个节点出现的次数与其核心数相同。因此,在具有每个节点8个核心的4节点集群上,您可以请求最多32个进程,并期望接近完美的加速。(当然,如果您的代码和算法允许这样做。)在该集群上请求9个进程可能会将8个进程放在一个节点上,第9个进程放在另一个节点上,这对性能来说显然不是很好。您希望您的集群软件带有一个比这更好地分配进程的mpirun。
从MPI作业的性能角度来看,有一些明确的规则: 1)如果您的代码是纯MPI代码(未使用openMP调整的BLAS),请关闭超线程并将每个节点作业的任务数设置为节点的核心数。 2)如果您的代码是MPI + openMP,则可以将PPN(每个节点的进程数)设置为节点的核心数,并将OMP_NUM_THEADS设置为2(如果每个核心有两个硬件线程)。 3)如果您的代码是MPI + openMP且您的集群非常庞大,则可以将PPN(每个节点的进程数)设置为1,将OMP_NUM_THEADS设置为逻辑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
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中的讨论。