OpenMP 和 MPI 混合程序

Posted

技术标签:

【中文标题】OpenMP 和 MPI 混合程序【英文标题】:OpenMP and MPI hybrid program 【发布时间】:2012-10-20 02:51:00 【问题描述】:

我有一台有 8 个处理器的机器。我想在我的代码上交替使用 OpenMP 和 MPI:

OpenMP 阶段:

排名 1-7 在 MPI_Barrier 上等待 rank 0 将所有 8 个处理器与 OpenMP 一起使用

MPI 阶段:

rank 0 达到障碍,所有 rank 各使用一个处理器

到目前为止,我已经完成了:

将 I_MPI_WAIT_MODE 设置为 1,以便 1-7 级在屏障上时不使用 CPU。 将 omp_set_num_threads(8) 设置为 0 级,以便启动 8 个 OpenMP 线程。

这一切都奏效了。 Rank 0 确实启动了 8 个线程,但都仅限于一个处理器。在 OpenMP 阶段,我得到 0 级的 8 个线程在一个处理器上运行,而所有其他处理器都处于空闲状态。

如何告诉 MPI 允许 0 级处理器使用其他处理器?我正在使用 Intel MPI,但如果需要,可以切换到 OpenMPI 或 MPICH。

【问题讨论】:

我认为这应该可行。你确定没有启用固定?检查I_MPI_PIN 设置。 您肯定启用了进程固定。诀窍是,如果您禁用它,您的 MPI 进程将不再受核心约束,并且 MPI 部分的性能会降低。您可以通过编程更改 CPU 掩码 - 保存它,允许 OpenMP 阶段的所有处理器,恢复掩码。 【参考方案1】:

以下代码显示了一个示例,说明如何在 OpenMP 部分之前保存 CPU 关联掩码,将其更改为在并行区域期间允许所有 CPU,然后恢复之前的 CPU 关联掩码。该代码是特定于 Linux 的,如果您不通过 MPI 库启用进程锁定,则没有任何意义 - 激活 通过在 Open MPI 中将 --bind-to-core--bind-to-socket 传递给 mpiexec停用通过在 Intel MPI 中将 I_MPI_PIN 设置为 disable(4.x 上的默认设置是固定进程)。

#define _GNU_SOURCE

#include <sched.h>

...

cpu_set_t *oldmask, *mask;
size_t size;
int nrcpus = 256; // 256 cores should be more than enough
int i;

// Save the old affinity mask
oldmask = CPU_ALLOC(nrcpus);
size = CPU_ALLOC_SIZE(nrcpus);
CPU_ZERO_S(size, oldmask);
if (sched_getaffinity(0, size, oldmask) == -1)  error 

// Temporary allow running on all processors
mask = CPU_ALLOC(nrcpus);
for (i = 0; i < nrcpus; i++)
   CPU_SET_S(i, size, mask);
if (sched_setaffinity(0, size, mask) == -1)  error 

#pragma omp parallel



CPU_FREE(mask);

// Restore the saved affinity mask
if (sched_setaffinity(0, size, oldmask) == -1)  error 

CPU_FREE(oldmask);

...

您还可以调整 OpenMP 运行时的固定参数。对于GCC/libgomp,关联由GOMP_CPU_AFFINITY 环境变量控制,而对于英特尔编译器,它是KMP_AFFINITY。如果 OpenMP 运行时将提供的关联掩码与进程的关联掩码相交,您仍然可以使用上面的代码。

只是为了完整起见 - 在 Windows 上保存、设置和恢复关联掩码:

#include <windows.h>

...

HANDLE hCurrentProc, hDupCurrentProc;
DWORD_PTR dwpSysAffinityMask, dwpProcAffinityMask;

// Obtain a usable handle of the current process
hCurrentProc = GetCurrentProcess();
DuplicateHandle(hCurrentProc, hCurrentProc, hCurrentProc,
                &hDupCurrentProc, 0, FALSE, DUPLICATE_SAME_ACCESS);

// Get the old affinity mask
GetProcessAffinityMask(hDupCurrentProc,
                       &dwpProcAffinityMask, &dwpSysAffinityMask);

// Temporary allow running on all CPUs in the system affinity mask
SetProcessAffinityMask(hDupCurrentProc, &dwpSysAffinityMask);

#pragma omp parallel



// Restore the old affinity mask
SetProcessAffinityMask(hDupCurrentProc, &dwpProcAffinityMask);

CloseHandle(hDupCurrentProc);

...

应该使用单个处理器组(最多 64 个逻辑处理器)。

【讨论】:

【参考方案2】:

感谢大家的cmets和答案。你没事。都是关于“PIN”选项的。

为了解决我的问题,我只需要:

I_MPI_WAIT_MODE=1

I_MPI_PIN_DOMAIN=omp

就这么简单。现在所有处理器都可用于所有等级。

选项

I_MPI_DEBUG=4

显示每个等级获得的处理器。

【讨论】:

您所做的是有效地禁用进程固定 - 固定到所有可用 CPU 的进程根本没有固定。

以上是关于OpenMP 和 MPI 混合程序的主要内容,如果未能解决你的问题,请参考以下文章

LSF 中的混合 MPI/OpenMP

在混合 MPI/OpenMP 中进行 MPI 调用的线程

确保混合 MPI / OpenMP 在不同的内核上运行每个 OpenMP 线程

MPI和OpenMP混合编程计算pi π值

在 MPICH 中执行混合 OpenMP/MPI 作业

基于 MPI/OpenMP 混合编程的大规模多体(N-Body)问题仿真实验