微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

对 OMP_NUM_THREADS 和 numactl NUMA-cores 绑定感到困惑

如何解决对 OMP_NUM_THREADS 和 numactl NUMA-cores 绑定感到困惑

我对同一 python 命令的多次启动如何绑定到 NUMA Xeon 机器上的内核感到困惑。

我读到 OMP_NUM_THREADS env var 设置为 numactl 进程启动的线程数。因此,如果我在超线程 HT 机器(下面的 lscpu 输出)上使用 numactl --physcpubind=4-7 --membind=0 python -u test.py 运行 OMP_NUM_THREADS=4,它会将这个 numactl 进程限制为 4 个线程。 但是由于机器有 HT,我不清楚上面的 4-7 是 4 个物理的还是 4 个逻辑的。

  • 如何找出 0-23,96-119 中的哪些 numa-node-0 核心是物理核心,哪些是逻辑核心? 96-119 都是合乎逻辑的还是散布的?

  • 如果 4-7 都是物理内核,那么在 HT 开启的情况下,只需要 2 个物理内核,那么其他 2 个会怎样?

  • 在将线程绑定到物理内核时,在哪里调用 OpenMP 库?

(根据我有限的理解,我可以使用不同的 numactl 绑定在 python main.py shell 中启动命令 sh 20 次,并且 OMP_NUM_THREADS 仍然适用,即使我没有明确 > 在任何地方使用 MPI 库,对吗?)

Architecture:                    x86_64
cpu op-mode(s):                  32-bit,64-bit
Byte Order:                      Little Endian
Address sizes:                   46 bits physical,48 bits virtual
cpu(s):                          192
On-line cpu(s) list:             0-191
Thread(s) per core:              2
Core(s) per socket:              48
Socket(s):                       2
NUMA node(s):                    4
vendor ID:                       GenuineIntel
cpu family:                      6
Model:                           85
Model name:                      Intel(R) Xeon(R) Platinum 9242 cpu @ 2.30GHz
Stepping:                        7
Frequency boost:                 enabled
cpu MHz:                         1000.026
cpu max MHz:                     2301,0000
cpu min MHz:                     1000,0000
BogoMIPS:                        4600.00
L1d cache:                       3 MiB
L1i cache:                       3 MiB
L2 cache:                        96 MiB
L3 cache:                        143 MiB
NUMA node0 cpu(s):               0-23,96-119
NUMA node1 cpu(s):               24-47,120-143
NUMA node2 cpu(s):               48-71,144-167
NUMA node3 cpu(s):               72-95,168-191

解决方法

我读到 OMP_NUM_THREADS env var 设置了为 numactl 进程启动的线程数。

numactl 不启动线程。它控制进程或共享内存的 NUMA 策略。但是,OpenMP 运行时可能会根据 numactl 设置的环境调整区域创建的线程数(尽管 AFAIK 标准未定义此行为)。您应该使用环境变量 OMP_NUM_THREADS 来设置线程数。您可以使用环境变量 OMP_DISPLAY_ENV 检查 OpenMP 配置。

如何找出 0-23,96-119 中的 numa-node-0 内核中哪些是物理内核,哪些是逻辑内核? 96-119 都是合乎逻辑的还是穿插在一起的?

这有点复杂。物理 ID 是 /proc/cpuinfo 中可用的 ID。它们不能保证随着时间的推移保持不变(例如,它们可以在机器重新启动时发生变化)也不能保证“直观”(即遵循规则,例如对于彼此靠近的线程/核心是连续的)。应该避免手动对它们进行硬编码。例如BIOS 更新或内核更新可能会导致以不同的顺序枚举逻辑内核。

您可以使用出色的工具 hwloc 将定义明确的确定性逻辑 ID 转换为物理 ID。在这里,您不能完全确定 0 和 96 是共享同一个内核的两个线程(尽管对于您的处理器来说这可能是正确的,它看起来内核从每个物理内核中枚举了一个逻辑内核作为内核 0..95,然后 96..191 用于每个物理内核上的另一个逻辑内核)。另一种常见的可能性是 Linux 连续做每个物理内核的两个逻辑内核,使逻辑内核 2n 和 2n+1 共享一个物理内核。

如果 4-7 个都是物理内核,那么在 HT 开启的情况下,只需要 2 个物理内核,那么其他 2 个会怎样?

--physcpubind

numctl 接受物理 CPU 编号,如 /proc/cpuinfo 的“processor”字段中显示的关于 the documentation。因此,此处的 4-7 应被解释为物理线程 ID。两个线程 ID 可以引用同一个物理内核(在启用超线程的英特尔处理器上总是如此)。

在将线程绑定到物理内核时,在哪里调用 OpenMP 库?

AFAIK,这是依赖于所使用的 OpenMP 运行时的实现(例如 GOMP、IOMP 等)。当遇到第一个并行部分时,OpenMP 运行时的初始化通常会延迟完成。对于绑定,一些运行时手动读取 /proc/cpuinfo,而另一些运行时使用 hwloc。如果您想要确定性绑定,那么您应该使用 OMP_PLACESOMP_PROC_BIND 环境变量来告诉运行时使用自定义的用户定义方法而不是默认方法来绑定线程。


如果你想安全和便携,请使用以下配置(使用 Bash):

OMP_NUM_THREADS=4
OMP_PROC_BIND=TRUE
OMP_PLACES={$(hwloc-calc --physical-output --sep "},{" --intersect PU core:all.pu:0)}

OpenMP 线程将被安排在 OpenMP 位置上。上述配置配置了 OpenMP 运行时,以便有 4 个线程静态映射到 4 个不同的固定内核。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。