以下代码显示了一个示例,说明如何在 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 个逻辑处理器)。