Hilo de afinidad con Windows, MSVC y OpenMP
Quiero vincular los hilos de mi código a cada núcleo físico. Con GCC lo hice con éxitosched_setaffinity
así que ya no tengo que configurarexport OMP_PROC_BIND=true
. Quiero hacer lo mismo en Windows con MSVC. Windows y Linux utilizando una topología de subproceso diferente. Linux dispersa los hilos mientras que Windows usa una forma compacta. En otras palabras, en Linux con cuatro núcleos y ocho hiperprocesos solo necesito vincular los subprocesos a las primeras cuatro unidades de procesamiento. En Windows, los configuro en cualquier otra unidad de procesamiento.
He hecho esto exitosamente usandoSetProcessAffinityMask
. Puedo ver desde el Administrador de tareas de Windows cuando hago clic derecho en los procesos y hago clic en "Establecer afinidad" que cada otra CPU está configurada (0, 2, 4, 6 en mi sistema de ocho hiperprocesos). El problema es que la eficiencia de mi código es inestable cuando ejecuto. A veces es casi constante, pero la mayoría de las veces tiene grandes cambios. Cambié la prioridad a alta pero no hay diferencia. En Linux la eficiencia es estable. ¿Quizás Windows todavía está migrando los hilos? ¿Hay algo más que deba hacer para unir los hilos en Windows?
Aquí está el código que estoy usando
#ifdef _WIN32
HANDLE process;
DWORD_PTR processAffinityMask = 0;
//Windows uses a compact thread topology. Set mask to every other thread
for(int i=0; i<ncores; i++) processAffinityMask |= 1<<(2*i);
//processAffinityMask = 0x55;
process = GetCurrentProcess();
SetProcessAffinityMask(process, processAffinityMask);
#else
cpu_set_t mask;
CPU_ZERO(&mask);
for(int i=0; i<ncores; i++) CPU_SET(i, &mask);
sched_setaffinity(0, sizeof(mask), &mask);
#endif
Editar: aquí está el código que usé ahora, que parece ser estable en Linux y Windows
#ifdef _WIN32
HANDLE process;
DWORD_PTR processAffinityMask;
//Windows uses a compact thread topology. Set mask to every other thread
for(int i=0; i<ncores; i++) processAffinityMask |= 1<<(2*i);
process = GetCurrentProcess();
SetProcessAffinityMask(process, processAffinityMask);
#pragma omp parallel
{
HANDLE thread = GetCurrentThread();
DWORD_PTR threadAffinityMask = 1<<(2*omp_get_thread_num());
SetThreadAffinityMask(thread, threadAffinityMask);
}
#else
cpu_set_t mask;
CPU_ZERO(&mask);
for(int i=0; i<ncores; i++) CPU_SET(i, &mask);
sched_setaffinity(0, sizeof(mask), &mask);
#pragma omp parallel
{
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(omp_get_thread_num(),&mask);
pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask);
}
#endif