Харт Джонсон М.
Шрифт:
В приведенном ниже фрагменте кода представлен видоизмененный рабочий цикл, выполняющий две операции с семафором.
Можно предложить еще одну разновидность программы. Если некоторый рабочий поток потребляет "слишком много" ресурсов, то можно заставить его выжидать некоторое время, пока значение счетчика семафора не уменьшится на несколько единиц. Однако, как уже отмечалось в предыдущей главе, использование двух последовательных циклов ожидания может стать причиной взаимоблокировки (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), которая должна представлять собой подмножество значений маски родства процесса. Первоначально маска родства потока совпадает с маской родства процесса.