Il seguente codice mostra un esempio su come salvare la maschera di affinità CPU prima della parte OpenMP, modificarla per consentire tutte le CPU per la durata dell'area parallela e quindi ripristinare la maschera di affinità CPU precedente. Il codice è specifico per Linux e non ha senso se non si abilita il blocco dei processi dalla libreria MPI - attivato passando da --bind-to-core
a mpiexec
in Open MPI; disattivato impostando I_MPI_PIN
in disable
in Intel MPI (l'impostazione predefinita su 4.x è di bloccare i processi).
#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);
...
È anche possibile modificare gli argomenti pinning del OpenMP run-time. Per GCC/libgomp
l'affinità è controllata dalla variabile di ambiente GOMP_CPU_AFFINITY, mentre per i compilatori Intel è KMP_AFFINITY. È comunque possibile utilizzare il codice sopra se il runtime OpenMP interseca la maschera di affinità fornita con quella del processo.
Solo per ragioni di completezza - risparmio, impostazione e ripristinare la maschera di affinità su 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);
...
dovrebbe funzionare con un singolo gruppo processore (fino a 64 processori logici).
Penso che questo dovrebbe funzionare. Sei sicuro che il blocco non è abilitato? Controlla l'impostazione 'I_MPI_PIN'. –
Sicuramente è abilitato il blocco dei processi. Il trucco è che se lo disabiliti, i tuoi processi MPI non sarebbero più legati al core e le prestazioni della parte MPI diminuirebbero. È possibile modificare la maschera della CPU in modo programmato: salvarla, consentire tutti i processori per la fase OpenMP, ripristinare la maschera. –