Гибридная программа OpenMP и MPI
У меня есть машина с 8 процессоров. Я хочу чередовать использование OpenMP и MPI в моем коде следующим образом:
OpenMP фаза:
- ряды 1-7 подождите на MPI_Barrier
- ранг 0 использует все 8 процессоров с OpenMP
MPI фаза:
- ранг 0 достигает барьера, и все ранги используют один процессор каждый
пока что я сделал:
- установить I_MPI_WAIT_MODE 1, так что ряды 1-7 не используют процессор, находясь на барьере.
- установите omp_set_num_threads (8) в ранг 0, чтобы он запускал 8 потоков OpenMP.
все работает. Ранг 0 запустил 8 потоков, но все они ограничены одним процессором. На фазе OpenMP я получаю 8 потоков из ранга 0, работающих на одном процессоре, а все остальные процессоры простаивают.
Как сказать MPI, чтобы разрешить рангу 0 использовать другие процессоры? Я использую Intel MPI, но могу при необходимости переключитесь на OpenMPI или MPICH.
2 ответов
следующий код показывает пример того, как сохранить маску сходства ЦП перед частью OpenMP, изменить ее, чтобы разрешить все ЦП на время параллельной области, а затем восстановить предыдущую маску сходства ЦП. Код специфичен для Linux и не имеет смысла, если вы не включаете закрепление процесса библиотекой MPI -активирован, передав --bind-to-core
или --bind-to-socket
to mpiexec
в открытом MPI;деактивирован установка I_MPI_PIN
to disable
в Intel MPI (the по умолчанию на 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 переменная окружения, в то время как для компиляторов Intel это 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 логических процессоров).
спасибо всем за комментарии и ответы. С тобой все в порядке. Все дело в опции "PIN".
чтобы решить мою проблему, мне просто нужно было:
I_MPI_WAIT_MODE=1
I_MPI_PIN_DOMAIN=omp
просто. Теперь все процессоры доступны для всех рангов.
параметр
I_MPI_DEBUG=4
показывает, какие процессоры получает каждый ранг.