Категории
Самые читаемые
💎Читать книги // БЕСПЛАТНО // 📱Online » Компьютеры и Интернет » Программирование » Системное программирование в среде Windows - Джонсон Харт

Читаем без скачивания Системное программирование в среде Windows - Джонсон Харт

Читать онлайн Системное программирование в среде Windows - Джонсон Харт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 72 73 74 75 76 77 78 79 80 ... 142
Перейти на страницу:

Если ни один из этих методов не дает желаемого улучшения, то могло бы показаться, что нет иного выхода, кроме как уменьшить количество потоков, но при этом вы будете вынуждены заставлять одиночные потоки мультиплексировать те операции, которые естественнее было бы распределить между несколькими потоками. Выход из этой ситуации обеспечивают семафоры, которые дают возможность сохранить естественную многопоточную модель, но вместе с тем свести к минимуму количество активных потоков, конкурирующих между собой. Такое решение является концептуально простым, и его можно без труда включить в любую существующую прикладную программу, например TimedMutualExclusion. В системе "хозяин/рабочий" решение, носящее название "дросселя" семафора (semaphore throttle), использует следующую методику:

• Главный поток создает семафор с небольшим, например 4, максимальным значением параметра, представляющего максимально допустимое количество активных потоков, которое, например, можно принимать равным количеству процессоров, установленных в системе, для обеспечения приемлемой производительности. Начальное значение счетчика семафора также следует установить равным максимальному значению. Это число можно сделать параметром и подбирать его оптимальное значение экспериментальным путем так же, как и в случае спин-счетчиков. Другим возможным значением этого параметра может служить количество процессоров, которое может быть определено во время выполнения программы (см. следующий раздел).

• Каждый рабочий поток ожидает перехода семафора в сигнальное состояние, прежде чем войти в критический участок кода. Ожидание семафора может непосредственно предшествовать ожиданию мьютекса или объекта CS.

• Если максимальное значение счетчика семафора равно 1, то использование мьютекса становится излишним. Подобное решение нередко является наилучшим для SMP-систем. 

• Общий уровень состязательности между объектами CS или мьютексами снижается, если при сериализации выполнения потоков лишь небольшое количество потоков ожидают перехода мьютексов или объектов CS в сигнальное состояние.

Счетчик семафора просто представляет число потоков, которые могут быть активными в любой момент времени, и ограничивает количество потоков, соревнующихся между собой за право владения мьютексом, объектом CS или иным ресурсом. Главный поток даже может регулировать, или, как говорят, "дросселировать" (throttle) выполнение рабочих потоков и динамически настраивать работу приложения, ожидая, пока не уменьшится значение счетчика, если он решает, что уровень состязательности слишком высок, или увеличивая значение счетчика с помощью функции ReleaseSemaphore, чтобы дать возможность выполняться большему количеству потоков. Заметьте, однако, что максимальное значение счетчика семафора устанавливается при его создании, и изменить его впоследствии невозможно.

В приведенном ниже фрагменте кода представлен видоизмененный рабочий цикл, выполняющий две операции с семафором.

while (TRUE) { // Рабочий цикл

 WaitForSingleObject(hThrottleSem, INFINITE);

 WaitForSingleObject(hMutex, INFINITE);

 … Критический участок кода …

 ReleaseMutex(hMutex);

 ReleaseSemaphore(hThrottleSem, 1, NULL);

} // Конец рабочего цикла

Можно предложить еще одну разновидность программы. Если некоторый рабочий поток потребляет "слишком много" ресурсов, то можно заставить его выжидать некоторое время, пока значение счетчика семафора не уменьшится на несколько единиц. Однако, как уже отмечалось в предыдущей главе, использование двух последовательных циклов ожидания может стать причиной взаимоблокировки (deadlock) потоков. В следующей главе в одном из упражнений (упражнение 10.11) показано, как построить сложный объект семафора, допускающий атомарное выполнение многократных функций ожидания.

В уже упоминавшемся примере программы TimedMutualExclusion добавлен шестой параметр, являющийся начальным значением дроссельного счетчика семафора для количества активных потоков. Вы можете поэкспериментировать со значениями этого счетчика, как предлагается в одном из упражнений. На рис. 9.1 показана зависимость различных временных характеристик для шести потоков, синхронизируемых посредством одного объекта CS, от количества активных потоков, изменяющегося в интервале от 1 до 6. Во всех случаях объем выполняемой работы остается одним и тем же, но истекшее время резко увеличивается, когда количество активных потоков превышает 4.

Рис. 9.1. Зависимость производительности от количества потоков

Указанные зависимости получены на устаревших, медленных системах. Для системы Windows 2000 на базе процессора Intel 586 (Pentium), характеризующейся гораздо более высоким быстродействием, соответствующие значения истекшего времени для 1–6 потоков составили (в секундах) 0.8, 0.8, 2.3, 21.2, 28.4 и 29.0, и эти результаты могут быть последовательно воспроизведены. В этом случае ухудшение производительности становилось заметным, начиная уже с 3 активных потоков. В то же время, соответствующие временные характеристики, оцененные с использованием произвольно выбранной совокупности аналогичных систем, оказались примерно постоянными, независимо от количества активных потоков. Результаты некоторых экспериментов дают основания сделать следующие выводы:

• В системе NT5 достигнут значительный прогресс по сравнению с NT4, по следовательно демонстрирующей результаты, аналогичные тем, которые представлены на рис. 9.1.

• Получаемые результаты зависят от того, в каком режиме выполняются операции — приоритетном или фоновом, то есть, находится или не находится фокус на окне приложения, а также от присутствия в системе других выполняемых задач. 

• Как правило, мьютексы работают медленнее по сравнению с объектами CS, но в случае NT5 результаты остаются примерно постоянными, независимо от количества активных потоков.

• В SMP-системах наиболее предпочтительным вариантом является дросселирование семафора при значении счетчика равном 1. В этом случае мьютексы становятся ненужными. Так, в случае двухпроцессорной системы Xeon частотой 1.8 ГГц использованные времена для варианта CS при 1, 2 и 4 активных потоках составили 1.8, 33.0 и 31.9 секунды. Соответствующие времена в случае мьютекса составили 34.0, 66.5 и 65.0 секунды.

Резюме. Дросселирование семафоров может обеспечивать хорошую производительность как для приоритетных, так и для фоновых операций даже в случае систем, загруженных выполнением других-задач. Дроссели семафоров могут играть очень важную роль в случае SMP-систем, для которых количество активных потоков должно быть равным 1. В том, что касается производительности, семафоры, по-видимому, более эффективны, чем мьютексы.

Родство процессоров

Во всем предшествующем обсуждении предполагалось, что все процессоры SMP-системы доступны всем потокам, а планирование выполнения потоков и распределение процессоров между ними осуществляет ядро. По своей сути такой простой подход является вполне естественным и согласуется с природой SMP-систем. В то же время, имеется возможность назначать потокам определенные процессоры, задавая так называемое родство процессоров (processor affinity). Родство процессоров можно использовать в нескольких ситуациях.

• Процессор может быть назначен небольшой группе, состоящей из одной и более высокоприоритетных потоков.

• Рабочие потоки, конкурирующие за право владения единственным ресурсом, могут быть распределены для выполнения на одном процессоре, что позволяет избежать затруднений с производительностью в случае SMP-систем, о которых перед этим говорилось.

• Возможен и другой вариант, когда потоки распределяются по доступным процессорам.

• Различным процессорам можно назначать различные классы рабочих потоков.

Маски родства системы, процесса и потока

У каждого процесса имеется собственная маска родства процесса (process affinity mask), представляющая собой битовый вектор. Существует также маска родства системы (system affinity mask). 

• Маска родства системы отображает процессоры, сконфигурированные в системе.

• Маска родства процесса отображает процессоры, на которых разрешается выполнение потоков данного процесса.

• Каждый индивидуальный поток имеет маску родства потока (thread affinity mask), которая должна представлять собой подмножество значений маски родства процесса. Первоначально маска родства потока совпадает с маской родства процесса.

Существуют функции для получения и установки масок, хотя системную маску вы можете только считывать (получать), а маски потоков — только устанавливать. Функции установки масок используют дескрипторы потоков и процессов, поэтому процессы или потоки могут устанавливать маску родства друг для друга, если имеются соответствующие права доступа, или для самих себя. Установка маски никак не повлияет на поток, уже выполняющийся на процессоре, использование которого вы пытаетесь исключить данной маской.

1 ... 72 73 74 75 76 77 78 79 80 ... 142
Перейти на страницу:
На этой странице вы можете бесплатно скачать Системное программирование в среде Windows - Джонсон Харт торрент бесплатно.
Комментарии