Гибридная программа 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

показывает, какие процессоры получает каждый ранг.