Я хочу привязать потоки в моем коде к каждому физическому ядру.
С GCC я успешно сделал это с помощью sched_setaffinity
, поэтому мне больше не нужно устанавливать export OMP_PROC_BIND=true
. Я хочу сделать то же самое в Windows с MSVC. Windows и Linux с использованием другой топологии потоков. Linux рассеивает потоки, а окна используют компактную форму. Другими словами, в Linux с четырьмя ядрами и восемью гиперпотоками мне нужно привязать потоки к первым четырем процессорам. В Windows я устанавливаю их для каждого другого процессора.
Я успешно сделал это, используя SetProcessAffinityMask
. Я могу видеть из диспетчера задач Windows, когда я нажимаю правой кнопкой мыши на процессы и нажимаю "Установить аффинность", что каждый другой процессор установлен (0, 2, 4, 6 в моей восьми гиперпотоковой системе). Проблема в том, что эффективность моего кода нестабильна при запуске. Иногда он почти постоянный, но большую часть времени он имеет большие изменения. Я изменил приоритет на высокий, но это не имеет никакого значения. В Linux эффективность стабильна. Может быть, Windows все еще переносит потоки? Есть ли что-то еще, что мне нужно сделать, чтобы связать потоки в Windows?
Вот код, который я использую
#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
Изменить: вот код, который я использовал сейчас, который, кажется, стабилен в Linux и 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