从 MPI 程序中启动 OpenMP 程序

Launching OpenMP program from within MPI program

我想从程序中调用一个利用 OpenMP 并行化的库,该程序本身 运行 是通过 MPI 并行的。如果我只是 运行 我的 MPI 程序使用单个进程,那么当需要调用 OpenMP 库时,会正确生成 7 个额外的线程(对应于我机器上的核心数)并且任务是并行进行。如果我改为 运行 我的 MPI 程序在 2 个进程上并让每个进程调用 OpenMP 程序,每个进程都会产生自己的线程而不是像以前那样一起工作,从而使计算花费更长的时间。

我试过只让MPI主进程调用OpenMP库,而其他进程等待,但是这些进程(物理内核)根本不参与OpenMP计算。

我是否必须以某种方式告诉 MPI 程序它现在应该共同启动一个 OpenMP 程序?更复杂的是,我 运行 具有多个节点的集群上的 MPI 程序。仅在包含 MPI 主进程的节点上启动 OpenMP 程序是可以接受的。

具体来说,我的MPI程序是用Cython写的,用的是mpi4py。我使用 MPICH 作为 MPI 实现,但希望这并不重要。 OpenMP 程序是用 C 编写的,我通过 Cython 包装器调用它。

我找到了解决方案。

对 OpenMP 库的调用只能由单个 MPI 进程完成。在此调用之后插入一个标准的 MPI 屏障是不好​​的,因为这样的屏障占用了从属进程 100% 的 CPU 时间,没有给 OpenMP 库留下额外的工作量。相反,我们必须编写自己的屏障函数,它会定期 ping 主进程以询问 OpenMP 调用是否已完成。在两次这样的 ping 之间,从进程在给定的时间间隔内休眠,这意味着它们可以自由参与 OpenMP 计算。

此逻辑的示例在 Python 中实现如下,希望变量名的含义显而易见。

def sleeping_barrier(sleep_time=0.1):
    if master:
        # Signal slaves to continue
        for slave in range(1, nprocs):
            isend(True, dest=slave)
    else:
        # Wait for master
        while True:
            sleep(sleep_time)
            if iprobe():
                recv()  # Remember to receive the message
                break

# Do OpenMP library call
if master:
    call_openmp_lib()
sleeping_barrier()