Я написал небольшую тестовую программу, в которой пытаюсь использовать вызов Windows API SetThreadAffinityMask для привязки потока к одному узлу NUMA. Я получаю битовую маску ЦП узла с помощью вызова API GetNumaNodeProcessorMask, затем передаю эту битовую маску в SetThreadAffinityMask вместе с дескриптором потока, возвращенным GetCurrentThread. Вот сильно упрощенная версия моего кода:
// Inside a function called from a boost::thread
unsigned long long nodeMask = 0;
GetNumaNodeProcessorMask(1, &nodeMask);
HANDLE thread = GetCurrentThread();
SetThreadAffinityMask(thread, nodeMask);
DoWork(); // make-work function
Я, конечно, проверяю, возвращают ли вызовы API 0 в моем коде, и я также распечатал маску узла NUMA, и это именно то, что я ожидал. Я также последовал совету, данному в другом месте, и распечатал маску, возвращенную вторым идентичным вызовом SetThreadAffinityMask, и она соответствует маске узла.
Однако при наблюдении за монитором ресурсов во время выполнения функции DoWork работа распределяется между всеми ядрами, а не только между теми, к которым она якобы привязана. Есть ли какие-то ошибки, которые я мог пропустить при использовании SetThreadAffinityMask? Я использую 64-разрядную версию Windows 7 Professional, и функция DoWork содержит цикл, распараллеленный с OpenMP, который выполняет операции над элементами трех очень больших массивов (которые в совокупности все еще могут поместиться в узле).
Изменить: чтобы расширить ответ, данный Дэвидом Шварцем, в Windows любые потоки, порожденные OpenMP, НЕ наследуют сходство породившего их потока. Проблема именно в этом, а не в SetThreadAffinityMask.