Windows SetThreadAffinityMask не действует

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


person ahelwer    schedule 24.01.2012    source источник
comment
Вы сообщаете Windows, что потоку разрешено работать на всех процессорах узла. Вот что вы видите, это работает.   -  person Hans Passant    schedule 24.01.2012
comment
Вы уверены, что у вас есть ядра в разных регионах NUMA?   -  person David Schwartz    schedule 24.01.2012


Ответы (1)


Вы подтвердили, что конкретный поток, маска сходства которого выполнялась на ядре в другом узле numa? В противном случае он работает, как задумано. Вы устанавливаете маску процессора для одного потока, а затем наблюдаете за поведением группы потоков.

person David Schwartz    schedule 24.01.2012
comment
да. Я создал только один поток вне основного с помощью boost::threads, который вызвал функцию, которая привязала его к узлам NUMA, а затем вызвал DoWork(). Внутри DoWork() были созданы потоки OpenMP, которые должны иметь такое же сходство, как и родительский поток. Но единственный родительский поток, который должен был быть привязан к 6/24 ядрам, использовал все 24 ядра внутри DoWork(). - person ahelwer; 24.01.2012
comment
Нет такой вещи, как родительский поток. Потоки — это ресурсы процесса. Вероятно, ваша реализация OpenMP не создает потоки, а повторно использует существующие. Проверьте ветку, маску которой вы установили — готов поспорить, что она находится там, где вы указали. - person David Schwartz; 24.01.2012
comment
Из стандарта OpenMP: родительский поток: поток, который столкнулся с параллельной конструкцией и сгенерировал параллельный регион, является родительским потоком каждого из потоков в команде этого параллельного региона. Главный поток параллельного региона — это тот же поток, что и его родительский поток, в отношении любых ресурсов, связанных с потоком OpenMP. Хм, может быть, поток 0 — единственный, у которого установлено сходство. Я проверю. - person ahelwer; 24.01.2012
comment
Я имею в виду, что для планировщика такой вещи нет. Нет никакой гарантии, что потоки созданы только для этой конструкции. - person David Schwartz; 24.01.2012
comment
Или, говоря лучше, привязка между потоками и командами является динамической. Кроме того, связь между потоками OpenMP и потоками ОС не определена. - person David Schwartz; 24.01.2012
comment
Отлично. Поэтому я породил кучу потоков boost, привязал их всех к одному узлу и удалил распараллеливание OpenMP. Все потоки выполняются в ядрах, которые им разрешены. Из этого мы можем сделать вывод, что потоки OpenMP в Windows НЕ наследуют маску сходства потока, который их порождает. Это происходит в Linux, поэтому я ожидал, что это произойдет и в Windows. - person ahelwer; 24.01.2012