Я написал небольшую тестовую программу, в которой я пытаюсь использовать API-интерфейс Windows 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.