KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Прочая околокомпьтерная литература » Марк Руссинович - 2.Внутреннее устройство Windows (гл. 5-7)

Марк Руссинович - 2.Внутреннее устройство Windows (гл. 5-7)

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Марк Руссинович, "2.Внутреннее устройство Windows (гл. 5-7)" бесплатно, без регистрации.
Перейти на страницу:

ЭКСПЕРИМЕНТ: просмотр и изменение привязки процесса к процессорам

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 filesresource kitcpustres.exe c: tempcpustres.exe

2. Задайте маску привязки так, чтобы она заставляла потоки процесса выполняться на процессоре 0. Для этого в командной строке (предполагается, что путь к ресурсам прописан в переменной окружения PATH) введите:

imagecfg — а 1 c: tempcpustres.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 блоке потока ядра каждого потока хранятся номера двух особых процессоров:

идеального (ideal processor) — предпочтительного для выполнения данного потока;

последнего (last processor) — на котором поток работал в прошлый раз.


Идеальный процессор для потока выбирается случайным образом при его создании с использованием зародышевого значения (seed) в блоке процесса. Это значение увеличивается на 1 всякий раз, когда создается новый поток, поэтому создаваемые потоки равномерно распределяются по набору доступных процессоров. Например, первый поток в первом процессе в системе закрепляется за идеальным процессором 0, второй поток того же процесса — за идеальным процессором 1. Однако у следующего процесса в системе идеальный процессор для первого потока устанавливается в 1, для второго — в 2 и т. д. Благодаря этому потоки внутри каждого процесса равномерно распределяются между процессорами.

Заметьте: здесь предполагается, что потоки внутри процесса выполняют равные объемы работы. Ho в многопоточном процессе это обычно не так; в нем есть, как правило, один или более «служебных» потоков (housekeeping threads) и несколько рабочих. Поэтому, если в многопоточном приложении нужно задействовать все преимущества многопроцессорной платформы, целесообразно указывать номера идеальных процессоров для потоков вызовом функции SetTbreadIdealProcessor.

B системах с Hyperthreading следующим идеальным процессором является первый логический процессор на следующем физическом. Например, в двухпроцессорной системе с Hyperthreading логических процессоров — 4; если для первого потока идеальным процессором назначен логический процессор 0, то для второго потока имело бы смысл назначить таковым логический процессор 2, для третьего — логический процессор 1, для четвертого — логический процессор 3 и т. д. Тогда потоки равномерно распределялись бы по физическим процессорам.

B NUMA-системах идеальный узел для процесса выбирается при его (процесса) создании. Первому процессу назначается узел 0, второму — 1 и т. д. Затем идеальные процессоры для потоков процесса выбираются из идеального узла. Идеальным процессором для первого потока в процессе назначается первый процессор в узле. По мере создания дополнительных потоков в процессе за ними закрепляется тот же идеальный узел; следующий процессор в этом узле становится идеальным для следующего потока и т. д.


Алгоритмы планирования потоков в многопроцессорных системах

Теперь, описав типы многопроцессорных систем, поддерживаемых Windows, а также привязку потоков к процессорам и выбор идеального процессора, мы готовы объяснить вам применение этой информации при определении того, какие потоки выполняются и на каких процессорах. При этом система принимает два базовых решения:

выбор процессора для потока, который готов к выполнению;

выбор потока для конкретного процессора.


Выбор процессора для потока при наличии простаивающих процессоров

Как только поток готов к выполнению, Windows сначала пытается подключить его к простаивающему процессору. Если таких процессоров несколько, предпочтение отдается сначала идеальному процессору для данного потока, затем предыдущему, а потом текущему (т. е. процессору, на котором работает код, отвечающий за планирование). B Windows 2000, если все эти процессоры заняты, выбирается первый простаивающий процессор, на котором может работать данный поток, для чего сканируется маска свободных процессоров в направлении убывания их номеров.

B Windows XP и Windows Server 2003 выбор простаивающего процессора не так прост. Во-первых, выделяются простаивающие процессоры из числа тех, на которых маска привязки разрешает выполнение данного потока. Если система имеет архитектуру NUMA и в узле, где находится идеальный процессор для потока, есть простаивающие процессоры, то список всех простаивающих процессоров уменьшается до этого набора. Если в результате такой операции в списке не останется простаивающих процессоров, список не сокращается. Затем, если в системе работают процессоры с технологией Hyperthreading и имеется физический процессор, все логические процессоры которого свободны, список простаивающих процессоров уменьшается до этого набора. И вновь, если в результате такой операции в списке не останется простаивающих процессоров, список не сокращается.

Если текущий процессор (тот, который пытается определить, что делать с потоком, готовым к выполнению) относится к набору оставшихся простаивающих процессоров, поток планируется к выполнению именно на этом процессоре. A если текущий процессор не входит в список оставшихся простаивающих процессоров, если это система с технологией Hyperthreading и если есть простаивающий логический процессор на физическом, который содержит идеальный процессор для данного потока, то список простаивающих процессоров ограничивается этим набором. B ином случае система проверяет, имеются ли простаивающие логические процессоры на физическом, который содержит предыдущий процессор потока. Если такой набор не пуст, список простаивающих процессоров уменьшается до этого набора.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*