2.Внутреннее устройство Windows (гл. 5-7)
Шрифт:
Однако для повышения пропускной способности и/или оптимизации рабочих нагрузок на определенный набор процессоров приложения могут изменять маску привязки потока к процессорам. Это можно сделать на нескольких уровнях.
• Вызовом функции SetThreadAffintiyMask, чтобы задать маску привязки к процессорам для индивидуального потока;
• Вызовом функции SetProcessAffinityMask, чтобы задать маску привязки к процессорам для всех потоков в процессе. Диспетчер задач и Process Explorer предоставляют GUI-интерфейс
• Включением процесса в задание, в котором действует глобальная для задания маска привязки к процессорам, установленная через функцию SetInformationJobObject (о заданиях см. раздел «Объекты-задания» далее в этой главе.)
• Определением маски привязки к процессорам в заголовке образа с помощью, например, утилиты Imagecfg из Windows 2000 Server Resource Kit Supplement 1. (O формате образов в Windows см. статью «Portable Executable and Common Object File Format Specification в MSDN Library.)
B образе можно установить и «однопроцессорный» флаг (используя в Imagecfg ключ — u). Если этот флаг установлен, система выбирает один процессор в момент создания процесса и закрепляет его за этим процессом; при этом процессоры меняются от первого и до последнего по принципу карусели. Например, в двухпроцессорной системе при первом запуске образа, помеченного как однопроцессорный, он закрепляется за процессором 0, при втором — за процессором 1, при третьем — за процессором 0, при четвертом — за процессором 1 и т. д. Этот флаг полезен, когда нужно временно обойти ошибку в программе, связанную с неправильной синхронизацией потоков, но проявляющуюся только в многопроцессорных системах.
ЭКСПЕРИМЕНТ: просмотр и изменение привязки процесса к процессорам
B этом эксперименте вы модифицируете привязку процесса к процессорам и убедитесь, что привязка наследуется новыми процессами.
1. Запустите окно командной строки (cmd.exe).
2. Запустите диспетчер задач или Process Explorer и найдите cmd.exe в списке процессов.
3. Щелкните этот процесс правой кнопкой мыши и выберите команду Set Affinity (Задать соответствие). Должен появиться список процессоров. Например, в двухпроцессорной системе вы увидите окно, как на следующей иллюстрации.
4. Выберите подмножество доступных процессоров в системе и нажмите ОК. Теперь потоки процесса будут работать только на выбранных вами процессорах.
5. Запустите Notepad.exe из окна командной строки (набрав notepad.exe).
6. Вернитесь в диспетчер задач или Process Explorer и найдите новый процесс Notepad. Щелкните его правой кнопкой мыши и выберите Set Affinity. Вы должны увидеть список процессоров, выбранных вами для процесса cmd.exe. Это вызвано тем, что процессы наследуют привязки к процессорам от своего родителя.
ЭКСПЕРИМЕНТ: изменение маски
B этом эксперименте (который потребует доступа к многопроцессорной системе) вы измените маску привязки к процессорам для какой-нибудь программы, чтобы заставить ее работать на первом процессоре.
1. Создайте копию Cpustres.exe (эта утилита содержится в ресурсах Windows 2000). Например, если у вас есть каталог c: \temp, то в командной строке введите:
сору c: \program files\resource kit\cpustres.exe c: \temp\cpustres.exe
2. Задайте маску привязки так, чтобы она заставляла потоки процесса выполняться на процессоре 0. Для этого в командной строке (предполагается, что путь к ресурсам прописан в переменной окружения PATH) введите:
imagecfg — а 1 c: \temp\cpustres.exe
3. Теперь запустите модифицированную Cpustres из каталога c.\temp.
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.
Следовательно, изменение маски привязки для процесса или потока может привести к тому, что потоки будут получать меньше процессорного времени, чем обычно, поскольку это ограничивает Windows в выборе процессоров для данного потока. A значит, задавать маску привязки нужно с крайней осторожностью — в большинстве ситуаций оптимальнее оставить выбор за самой Windows.
B блоке потока ядра каждого потока хранятся номера двух особых процессоров: