使用MPI / OpenMP混合编程的奇怪问题。在并行区域中,OpenMP线程数始终为1

时间:2019-06-22 09:51:57

标签: multithreading mpi

系统配置:

Workstation with two Xeon E5-2620 V4 CPUs. Cent OS 7.3.

Openmpi-3.0.1, ifort 2015, gcc 4.8.6, intel MKL.

我在工作站上运行MPI / OpenMP混合程序。我想将1个MPI进程与8个OpenMP线程一起使用。但是,并行区域中使用的OpenMP线程始终为1。在具有Intel 9900K CPU的另一台计算机上,OpenMP线程的数量始终为2。对于两台计算机,我都通过调用omp_get_max_threads打印了OMP_NUM_THREADSOMP_NUM_THREADS为8,因为我已经设置了“ export OMP_NUM_THREADS=8”。真的很麻烦。

经过大约一天的学习,我意识到它与Openmpi参数“ -bind-to”有关。如果使用“ -bind-to-none”或“ -bind-to numa”,则该程序运行良好,因为每个MPI进程的CPU使用率为800%,并且在并行区域中获得了8倍的加速。如果我使用默认值“ -bind-to core”。 OpenMP线程数始终不是我期望的。因此,使用Xeon 2640的工作站已禁用超线程,因此实际使用的openmp线程始终为1。对于具有Intel i7-9900K的PC,启用了超线程,因此使用的OMP线程数为2

此外,如果我不使用“ -bind-to none/numa”参数,则omp_get_num_procs返回1。如果使用“ -bind-to none”,则omp_get_num_procs返回使用“ {{1}”时的处理器(CPU内核)数。 }“,omp_get_num_procs返回一个CPU中的CPU核心数。

我在这里发表我的经验,这可能会帮助其他人遇到类似的问题。

1 个答案:

答案 0 :(得分:0)

正如Gilles in comment所指出的,混合MPI + OpenMP运行中有两个地方可与cpu集一起使用。第一个是MPI库和mpirun(mpiexec)程序,该程序在可用节点及其可用CPU上进行MPI处理分发(借助于hwloc)。然后,每个启动的MPI进程都将具有一组允许的逻辑CPU内核,并且OpenMP(多线程)库将尝试使用这些可用资源。 OpenMP库(gcc的libgomp或intel的&llvm的openmprtl.org)可能会检查允许的内核集,以决定要使用的线程数。

当您想要“具有K个OpenMP线程的 N个MPI进程”时,应检查您的mpirun是否为每个MPI进程提供K个允许的内核。而且mpirun不会尊重您的OMP_NUM_THREADS env变量。

OpenMPI的mpirun具有有用的选项--report-bindings,以查看实际运行中允许的设置。它也有许多(不太容易使用)选项来更改绑定,如手册页所述 https://www.open-mpi.org/doc/v4.0/man1/mpirun.1.php

您可以尝试mpirun -n 1 --report-bindings true来查看实际的绑定,而无需启动程序。对于1个MPI进程和每个进程8个内核,请尝试使用选项“ --cpus-per-proc <#perproc>-将每个进程绑定到指定数量的cpus。

 mpirun -n 1 --cpus-per-proc 8 --report-bindings true

不建议使用此选项,但是它仍然可以工作,并且比“ --map-by <obj>:PE=n”要容易得多。 (我现在还不完全了解这种变体。可能是--map-by socket--bind-by socket可以帮助您将mpi进程绑定到CPU芯片的所有可用内核)

要找出逻辑cpu内核到超线程和实际cpu内核的映射,可以使用hwloc库及其工具lstopo https://www.open-mpi.org/projects/hwloc/doc/v2.0.4/a00312.php#cli_examples