这取决于很多因素,以至于不可能存在单一的“银弹”答案。这些因素包括计算强度(FLOPS/字节)以及本地数据量与进程之间传递的数据量之间的比率。它还取决于系统的架构。计算强度可以通过分析估计或使用 PAPI、Likwid 等分析工具进行测量。可以使用 lstopo 实用程序检查系统架构,该实用程序是 hwloc 库的一部分,它带有 Open MPI。不幸的是,lstopo 无法告诉您每个内存通道的速度以及 NUMA 节点之间的链接的速度/延迟。
是的,有:--report-bindings 使每个等级打印到其标准错误输出适用于它的亲和掩码。不同 Open MPI 版本的输出略有不同:
Open MPI 1.5.x显示亲和力掩码的十六进制值:
mpiexec --report-bindings --bind-to-core --bycore
[hostname:00599] [[10634,0],0] odls:default:fork binding child [[10634,1],0] to cpus 0001
[hostname:00599] [[10634,0],0] odls:default:fork binding child [[10634,1],1] to cpus 0002
[hostname:00599] [[10634,0],0] odls:default:fork binding child [[10634,1],2] to cpus 0004
[hostname:00599] [[10634,0],0] odls:default:fork binding child [[10634,1],3] to cpus 0008
这表明等级 0 的关联掩码设置为 0001,这允许它仅在 CPU 0 上运行。 Rank 1 将其关联掩码设置为 0002,这允许它仅在 CPU 1 上运行。以此类推。
mpiexec --report-bindings --bind-to-socket --bysocket
[hostname:21302] [[30955,0],0] odls:default:fork binding child [[30955,1],0] to socket 0 cpus 003f
[hostname:21302] [[30955,0],0] odls:default:fork binding child [[30955,1],1] to socket 1 cpus 0fc0
[hostname:21302] [[30955,0],0] odls:default:fork binding child [[30955,1],2] to socket 0 cpus 003f
[hostname:21302] [[30955,0],0] odls:default:fork binding child [[30955,1],3] to socket 1 cpus 0fc0
在这种情况下,关联掩码在003f 和0fc0 之间交替。二进制中的003f 是0000000000111111,这样的关联掩码允许每个偶数秩在0 到5 的CPU 上执行。0fc0 是0000111111000000,因此奇数秩只安排在5 到11 的CPU 上。
Open MPI 1.6.x 改为使用更好的图形显示:
mpiexec --report-bindings --bind-to-core --bycore
[hostname:39646] MCW rank 0 bound to socket 0[core 0]: [B . . . . .][. . . . . .]
[hostname:39646] MCW rank 1 bound to socket 0[core 1]: [. B . . . .][. . . . . .]
[hostname:39646] MCW rank 2 bound to socket 0[core 2]: [. . B . . .][. . . . . .]
[hostname:39646] MCW rank 3 bound to socket 0[core 3]: [. . . B . .][. . . . . .]
mpiexec --report-bindings --bind-to-socket --bysocket
[hostname:13888] MCW rank 0 bound to socket 0[core 0-5]: [B B B B B B][. . . . . .]
[hostname:13888] MCW rank 1 bound to socket 1[core 0-5]: [. . . . . .][B B B B B B]
[hostname:13888] MCW rank 2 bound to socket 0[core 0-5]: [B B B B B B][. . . . . .]
[hostname:13888] MCW rank 3 bound to socket 1[core 0-5]: [. . . . . .][B B B B B B]
每个插槽都以图形方式表示为一组方括号,每个核心由一个点表示。每个等级所绑定的核心由字母B 表示。进程只绑定到第一个硬件线程。
Open MPI 1.7.x 有点冗长,也了解硬件线程:
mpiexec --report-bindings --bind-to-core
[hostname:28894] MCW rank 0 bound to socket 0[core 0[hwt 0-1]]: [BB/../../../../..][../../../../../..]
[hostname:28894] MCW rank 1 bound to socket 0[core 1[hwt 0-1]]: [../BB/../../../..][../../../../../..]
[hostname:28894] MCW rank 2 bound to socket 0[core 2[hwt 0-1]]: [../../BB/../../..][../../../../../..]
[hostname:28894] MCW rank 3 bound to socket 0[core 3[hwt 0-1]]: [../../../BB/../..][../../../../../..]
mpiexec --report-bindings --bind-to-socket
[hostname:29807] MCW rank 0 bound to socket 0[core 0[hwt 0-1]], socket 0[core 1[hwt 0-1]], socket 0[core 2[hwt 0-1]], socket 0[core 3[hwt 0-1]], socket 0[core 4[hwt 0-1]], socket 0[core 5[hwt 0-1]]: [BB/BB/BB/BB/BB/BB][../../../../../..]
[hostname:29807] MCW rank 1 bound to socket 1[core 6[hwt 0-1]], socket 1[core 7[hwt 0-1]], socket 1[core 8[hwt 0-1]], socket 1[core 9[hwt 0-1]], socket 1[core 10[hwt 0-1]], socket 1[core 11[hwt 0-1]]: [../../../../../..][BB/BB/BB/BB/BB/BB]
[hostname:29807] MCW rank 2 bound to socket 0[core 0[hwt 0-1]], socket 0[core 1[hwt 0-1]], socket 0[core 2[hwt 0-1]], socket 0[core 3[hwt 0-1]], socket 0[core 4[hwt 0-1]], socket 0[core 5[hwt 0-1]]: [BB/BB/BB/BB/BB/BB][../../../../../..]
[hostname:29807] MCW rank 3 bound to socket 1[core 6[hwt 0-1]], socket 1[core 7[hwt 0-1]], socket 1[core 8[hwt 0-1]], socket 1[core 9[hwt 0-1]], socket 1[core 10[hwt 0-1]], socket 1[core 11[hwt 0-1]]: [../../../../../..][BB/BB/BB/BB/BB/BB]
Open MPI 1.7.x 还将--bycore 和--bysocket 选项替换为更通用的--rank-by <policy> 选项。