Приложения, которым нужно выжать максимум производительности из NUMA-систем, могут устанавливать маски привязки процесса к процессорам в определенном узле. Получить эту информацию позволяют функции, перечисленные в таблице 6-19. (Функции, с помощью которых можно изменять привязку потоков к процессорам, были перечислены в таблице 6-14.)
O том, как алгоритмы планирования учитывают особенности NUMA-систем, см. в разделе «Алгоритмы планирования потоков в многопроцессорных системах» далее в этой главе (а об оптимизациях в диспетчере памяти для использования преимуществ локальной для узла памяти см. в главе 7).
У каждого потока есть
Однако для повышения пропускной способности и/или оптимизации рабочих нагрузок на определенный набор процессоров приложения могут изменять маску привязки потока к процессорам. Это можно сделать на нескольких уровнях.
(o) Вызовом функции
(o) Вызовом функции
(o) Включением процесса в задание, в котором действует глобальная для задания маска привязки к процессорам, установленная через функцию
(o) Определением маски привязки к процессорам в заголовке образа с помощью, например, утилиты Imagecfg из Windows 2000 Server Resource Kit Supplement 1. (O формате образов в Windows см. статью «Portable Executable and Common Object File Format Specification в MSDN Library.)
B образе можно установить и «однопроцессорный» флаг (используя в Imagecfg ключ
ЭКСПЕРИМЕНТ: просмотр и изменение привязки процесса к процессорам
B этом эксперименте вы модифицируете привязку процесса к процессорам и убедитесь, что привязка наследуется новыми процессами.
1. Запустите окно командной строки (cmd.exe).
2. Запустите диспетчер задач или Process Explorer и найдите cmd.exe в списке процессов.
3. Щелкните этот процесс правой кнопкой мыши и выберите команду Set Affinity (Задать соответствие). Должен появиться список процессоров. Например, в двухпроцессорной системе вы увидите окно, как на следующей иллюстрации.
4. Выберите подмножество доступных процессоров в системе и нажмите ОК. Теперь потоки процесса будут работать только на выбранных вами процессорах.
5. Запустите Notepad.exe из окна командной строки (набрав
6. Вернитесь в диспетчер задач или Process Explorer и найдите новый процесс Notepad. Щелкните его правой кнопкой мыши и выберите Set Affinity. Вы должны увидеть список процессоров, выбранных вами для процесса cmd.exe. Это вызвано тем, что процессы наследуют привязки к процессорам от своего родителя.
ЭКСПЕРИМЕНТ: изменение маски привязки образа
B этом эксперименте (который потребует доступа к многопроцессорной системе) вы измените маску привязки к процессорам для какой-нибудь программы, чтобы заставить ее работать на первом процессоре.
1. Создайте копию Cpustres.exe (эта утилита содержится в ресурсах Windows 2000). Например, если у вас есть каталог c: emp, то в командной строке введите:
2. Задайте маску привязки так, чтобы она заставляла потоки процесса выполняться на процессоре 0. Для этого в командной строке (предполагается, что путь к ресурсам прописан в переменной окружения PATH) введите:
3. Теперь запустите модифицированную Cpustres из каталога c. emp.
4. Включите два рабочих потока и установите уровень активности обоих потоков в Maximum (не Busy). Окно Cpustres должно выглядеть следующим образом.
5. Найдите процесс Cpustres в Process Explorer или диспетчере задач, щелкните его правой кнопкой мыши и выберите Set Affinity. Вы должны увидеть, что процесс привязан к процессору 0.
6. Посмотрите общесистемное использование процессора, выбрав Show, System Information (в Process Explorer) или открыв вкладку Performance (в диспетчере задач). Если в системе нет других процессов, занятых интенсивными вычислениями, общая процентная доля использования процессорного времени должна составить примерно 1 /(число процессоров) (скажем, около 50% в двухпроцессорной системе или около 25% в четырехпроцессорной), потому что оба потока в Cpustres привязаны к одному процессору и остальные процессоры простаивают. 7. Наконец, измените маску привязки процесса Cpustres так, чтобы разрешить ему выполнение на всех процессорах. Снова проверьте общесистемное использование процессорного времени. Теперь оно должно быть 100% в двухпроцессорной системе, 50% в четырехпроцессорной и т. д.
Windows не перемещает уже выполняемый поток с одного процессора на второй, чтобы готовый поток с маской привязки именно к первому процессору немедленно начал на нем работать. Рассмотрим, например, такой сценарий: к процессору 0 подключен поток с приоритетом 8, который может работать на любом процессоре, а к процессору 1 – поток с приоритетом 4, который тоже может выполняться на любом процессоре. Ho вот готов поток с приоритетом 6, привязанный только к процессору 0. Что произойдет? Windows не станет переключать поток с приоритетом 8 на процессор 1 (вытесняя при этом поток с приоритетом 4), и поток с приоритетом 6 будет ждать освобождения процессора 0.