- •Глава 10
- •10.1. Многопроцессорное планирование
- •Назначение процессов процессорам
- •10.2. Планирование реального времени
- •10.3 Планирование в linux
- •10.4. Планирование в unix svr4
- •10.5. Планирование windows 2000
- •Многопроцессорное планирование
- •10.6. Резюме, ключевые термины и контрольные вопросы
- •10.7. Рекомендуемая литература
- •10.8. Задачи
Назначение процессов процессорам
В предположении единообразия архитектуры многопроцессорной системы (в том смысле, что ни один процессор физически не отличается от других в плане доступа к основной памяти или устройствам ввода-вывода) простейший подход к планированию состоит в рассмотрении процессоров как единого ресурса и назначении процессов процессорам по требованию. При таком подходе возникает один вопрос: должно ли такое назначение быть статическим или динамическим?
Если процесс назначается одному процессору постоянно — от момента активации и до его завершения, — то для каждого процессора следует поддерживать отдельную краткосрочную очередь. Такой подход способствует уменьшению накладных расходов планирования процессов (поскольку назначение процесса процессору выполняется только один раз). Кроме того, использование выделенных процессоров обеспечивает возможность применения стратегии, известной как групповое (group), или бригадное (gang), планирование (о нем мы поговорим позже).
Недостатком статического распределения является то, что когда один процесс загружен работой, другой может простаивать. Для предотвращения такой ситуации можно использовать очередь, общую для всех процессоров. Все процессы попадают в одну глобальную очередь и передаются для выполнения любому свободному процессору. Таким образом, при этом подходе в течение жизни процесс может в разное время выполняться на разных процессорах. В сильносвязанных системах с общей памятью информация контекста всех процессов доступна всем процессорам и, следовательно, стоимость планирования процесса не зависит от того, какой из процессов оказывается выбранным.
Независимо от выбранного типа распределения, используются два основных подхода к назначению процессов процессорам: ведущий/ведомый процессоры и равноправные процессоры. В случае использования архитектуры "ведущий/ведомый" ключевые функции операционной системы всегда выполняются на одном специально выделенном процессоре; все остальные процессоры могут выполнять только пользовательские приложения. Ведущий процессор отвечает за планирование заданий. Когда активный процесс на ведомом процессоре требует определенного обслуживания (например, осуществляет вызов ввода-вывода), он должен послать запрос ведущему процессору и ожидать завершения сервиса. Такой подход достаточно прост и требует внесения небольших дополнений в однопроцессорную многозадачную операционную систему. Упрощается при таком подходе и разрешение конфликтов, поскольку один процессор управляет всей памятью и ресурсами ввода-вывода. Однако у такого подхода имеются два недостатка: (1) сбой ведущего процессора приводит к неработоспособности всей системы в целом, и (2) ведущий процессор превращается в узкое место системы, определяющее ее производительность в целом.
При использовании архитектуры равноправных процессоров операционная система может выполняться на любом из процессоров, и каждый процессор самостоятельно планирует свою работу, беря процессы для выполнения из общего пула. Такой подход усложняет операционную систему, которая должна гарантировать, что никакие два процессора не выберут одновременно один и тот же процесс для выполнения и что не будет никаких потерь из очереди. Здесь должна быть применена технология, использующаяся для разрешения конфликтов и синхронизации запросов к ресурсам.
Конечно, кроме этих крайностей, имеется ряд других подходов. Например, для работы операционной системы может быть выделен не один процессор, а несколько; возможно использование системы приоритетов для отделения процессов ядра от прочих процессов
Использование многозадачности отдельных процессоров
Когда каждый процесс назначается процессору статически на все время жизни, возникает новый вопрос: должен ли этот процессор быть многозадачным? На первый взгляд, такой вопрос кажется просто странным; ведь мы уже выяснили, что использование процессора в однозадачном режиме, при том, что процесс может обращаться к устройствам ввода-вывода, является попросту расточительным.
При рассмотрении традиционных многопроцессорных систем, работающих с независимыми процессами или с большим зерном синхронизации (см. табл. 10.1), очевидно, что каждый отдельный процессор должен иметь возможность переключаться между процессами для повышения загруженности, а следовательно. и производительности. Однако в случае использования приложений со средней зернистостью синхронизации ситуация не столь ясна. При доступности множества процессоров правило максимально возможной загруженности процессора перестает быть первостепенным; вместо этого первостепенную важность приобретает обеспечение максимальной средней производительности приложений. Приложение, состоящее из множества потоков, может плохо работать до тех пор, пока его потоки не получат возможность одновременного выполнения.
Диспетчеризация процессов
Последний конструкторский вопрос, связанный с многопроцессорным планированием, является вопросом выбора процесса для выполнения. Мы видели, что в многозадачной системе с одним процессором использование приоритетов или сложных алгоритмов, учитывающих время работы процессов, может существенно повысить производительность системы по сравнению с использованием стратегии "первым пришел — первым обслужен". При рассмотрении многопроцессорных систем более простой подход может оказаться более эффективным в силу уменьшения накладных расходов. В случае планирования потоков в действие вступают новые характеристики, которые могут оказаться более важными, чем приоритеты или история выполнения. Позже мы детально рассмотрим эти вопросы.
Планирование процессов
В большинстве традиционных многопроцессорных систем назначение процессов процессорам отсутствует. Вместо этого используется общая очередь для всех процессов, либо — в случае применения схемы с учетом приоритетов — множество очередей. В любом случае мы можем рассматривать систему как очередь с несколькими серверами.
Рассмотрим систему с двумя процессорами, в которой каждый процессор обладает производительностью, в два раза меньшей, чем производительность процессора в однопроцессорной системе. В [SAUE81] проведено сравнение стратегии планирования FCFS с круговым планированием и планированием на основе минимального остающегося времени выполнения. При круговом планировании квант времени считался большим по сравнению с затратами на переключение контекстов задач и малым — по сравнению со временем обслуживания, которое и было основным объектом исследования. Полученные результаты в значительной степени зависят от того, насколько велика разница во времени обслуживания разных процессов. Количественно эту разницу можно выразить как коэффициент вариации Cs. Значение Сs= 0 соответствует отсутствию вариации времени обслуживания (время обслуживания всех процессов одинаково). Увеличение значения Cs соответствует росту изменчивости времени обслуживания, т.е. чем выше это значение, тем больше отклонения отдельных значений времени обслуживания от среднего. Значения коэффициента вариации, превышающие 5, не являются чем-то необычным для распределения времени обслуживания процессов.
На рис. 10.1,а приведено сравнение пропускных способностей кругового планирования и планирования FCFS как функций коэффициента вариации Cs.Обратите внимание, что разница между ними существенно меньше в системах с двумя процессорами. При наличии двух процессоров длинный процесс не так сильно влияет на систему в целом, поскольку другие процессы могут использовать второй процессор. Аналогичные результаты можно увидеть и на рис. 10.1,6.
В работе [SAUE81] такой же анализ был проведен для самых разных предположений о степени многозадачности, соотношении количества процессов, ориентированных на вычисления и на ввод-вывод, и использовании приоритетов. Общий вывод, сделанный в этой работе, следующий: влияние выбора стратегии планирования на производительность при наличии двух процессоров существенно меньше, чем при наличии лишь одного. Очевидно, что с ростом количества процессоров рассматриваемое влияние уменьшается. Следовательно, простейшую стратегию FCFS (в том числе и в схеме со статическими приоритетами) можно вполне успешно применять в многопроцессорной системе.
Планирование потоков
Как мы видели, в случае использования потоков концепция выполнения отделена от остальной части определения процесса. Приложение может быть реализовано как множество взаимодействующих потоков, выполняющихся параллельно в одном адресном пространстве.
В однопроцессорной системе потоки могут использоваться для структуризации программы и с целью перекрытия операций ввода-вывода вычислительной работой. Поскольку по сравнению с переключением процессов переключение потоков осуществляется с гораздо меньшими затратами, оно имеет преимущество в стоимости. Однако полная мощь потоков проявляется только в многопроцессорных системах, где потоки могут использоваться для достижения истинно параллельных вычислений в рамках одного приложения. Если различные потоки одного приложения выполняются одновременно на разных процессорах, можно достичь резкого повышения производительности. Однако в приложении с интенсивным взаимодействием потоков (среднезернистая синхронизация) небольшие различия в стратегии управления потоками и их планирования могут привести к существенному изменению производительности [ANDE89], Планирование потоков в многопроцессорных системах является областью интенсивных исследовательских работ; здесь же мы рассмотрим только ключевые вопросы данной темы и основные подходы при их решении.
Среди множества вариантов планирования потоков в многопроцессорных системах и назначения процессов процессорам можно выделить четыре основных подхода.
• Разделение загрузки. Процессы не назначаются конкретным процессорам.
Поддерживается глобальная очередь готовых к выполнению потоков, и каждый процессор в состоянии простоя выбирает поток из этой очереди. Термин разделение загрузки (load sharing) используется, чтобы отличать эту стратегию от схем со сбалансированной загрузкой, в которых работа распределяется на более постоянной основе (см., например, [FEIT90a]).
• Бригадное планирование. Множество связанных потоков распределяются для одновременной работы среди множества процессоров, по одному потоку на процессор.
• Назначение процессоров. В противоположность подходу с разделением нагрузки этот подход обеспечивает неявное планирование путем назначения потоков процессорам. Каждой программе на время ее выполнения выделяется количество процессоров, равное количеству потоков программы. По окончании работы программы процессоры возвращаются в общий пул для распределения другим программам.
• Динамическое планирование. Количество потоков процесса может изменяться во время работы.
Разделение загрузки
Разделение загрузки представляет собой, пожалуй, наиболее простой подход, непосредственно переносимый из однопроцессорной среды в многопроцессорную. Он имеет ряд достоинств.
• Загрузка равномерно распределяется между процессорами, обеспечивая отсутствие простоя процессоров при наличии работы.
• Не требуется централизованный планировщик; когда процессор становится доступным, он сам выполняет подпрограмму планирования операционной системы для выбора очередного потока.
• Глобальная очередь может быть организована с использованием любой из приведенных в главе 9, "Планирование в системах с одним процессором", схем, включая схемы с использованием приоритетов и с учетом истории выполнения.
В [LEUT90] проанализированы три различные версии разделения загрузки.
• Первым пришел — первым обслужен. При поступлении в систему нового задания каждый из его потоков помещается в конец разделяемой очереди. Когда процессор становится свободным, он выбирает очередной готовый к исполнению поток и работает с ним до его завершения или блокирования.
• Выбор процесса с наименьшим числом потоков. Разделяемая очередь готовых к выполнению потоков организована как приоритетная, причем наивысший приоритет отдается потокам тех заданий, у которых осталось наименьшее число не распланированных потоков. Задания с одинаковым приоритетом упорядочиваются в соответствии со временем поступления в систему. Как и в случае использования стратегии FCFS, поток выполняется до его завершения или блокирования.
• Выбор процесса с наименьшим числом потоков с применением вытеснения.
Наивысший приоритет получают задания с наименьшим количеством не распланированных потоков. Поступившие задания с меньшим, чем у выполняющегося, количеством потоков вытесняют потоки, выполняющиеся в настоящее время.
Исследования, проведенные с помощью имитационного моделирования, показали, что по большому количеству характеристик стратегия FCFS превосходит две остальные стратегии из приведенного списка. Кроме того, авторы обнаружили, что некоторые виды бригадного планирования, обсуждающиеся в следующем подразделе, в целом превосходят разделение загрузки, которое имеет, к тому же, ряд недостатков.
• Центральная очередь занимает область памяти, доступ к которой должен производиться с обеспечением взаимоисключений. Следовательно, это может стать узким местом, если несколько процессоров одновременно обратятся к очереди за порцией работы. При небольшом количестве процессоров эта проблема не является критической, но при наличии в системе десятков, а то и сотен процессоров затор в этом месте представляется совершенно реальным.
• Низкая вероятность того, что вытесняемые потоки продолжат выполнение на тех же процессорах, снижает эффективность использования локальных кэшей процессоров.
• Если все потоки рассматриваются как один общий пул, маловероятно, чтобы все потоки одной программы получили одновременный доступ к процессорам. При необходимости высокой степени координации между потоками программы это приводит к существенному снижению ее общей производительности.
Несмотря на потенциальные недостатки, это одна из наиболее часто используемых в современных многопроцессорных системах схем.
Усовершенствованная схема разделения загрузки используется в операционной системе Mach [BLAC90, WEND89]. Операционная система поддерживает локальную очередь для каждого процессора и совместно используемую глобальную очередь. Локальная очередь используется потоками, которые временно связаны с определенным процессором. Процессор сперва исследует локальную очередь, тем самым отдавая приоритет связанным с ним потокам перед не связанными. Примером связанных потоков может служить использование одного или нескольких процессоров для выполнения процессов, являющихся частью операционной системы. Другим примером являются потоки одного приложения, распределенные между рядом процессоров; при наличии соответствующего дополнительного программного обеспечения поддерживается обсуждающееся ниже бригадное планирование.
Бригадное планирование
Концепция одновременного выполнения множества процессов на множестве Процессоров предшествует использованию потоков. В [JONE80] эта концепция названа групповым планированием, и там же перечислены ее основные достоинства.
• Если тесно связанные процессы выполняются параллельно, блокирование, вызванное синхронизацией, снижается; кроме того, требуется меньше переключений процессов. В целом это приводит к повышению производительности процесса.
• Накладные расходы, связанные с планированием, уменьшаются, поскольку одно решение влияет одновременно на целый ряд процессов и процессоров.
В многопроцессорной системе Cm* используется термин сопланирование (coscheduling") [GEHR87]. Сопланирование основано на концепции планирования связанного множества задач, отдельные элементы которого достаточно малы и, следовательно, близки к концепции потоков.
Термин бригадное планирование (gang scheduling) применяется к одновременному планированию потоков, составляющих единый процесс [FEIT90b]. Оно необходимо для приложений с синхронизацией от среднезернистой до мелкозернистой, производительность которых резко падает, если какая-то часть приложения не работает, в то время как другие готовы к выполнению. Этот метод вполне применим и к другим приложениям с параллельными вычислениями, которые не настолько чувствительны в плане зависимости общей производительности от синхронизации работы потоков. Бригадное планирование общепризнанно, и его реализации имеются во множестве многопроцессорных операционных систем.
Один очевидный путь улучшения производительности отдельного приложения при бригадном планировании заключен в минимизации переключения процессов. Предположим, что один поток процесса выполняется и достигает точки синхронизации с другим потоком того же процесса. Если этот второй поток не выполняется, но готов к выполнению, то первый поток приостанавливается в ожидании, когда некоторым другим процессором не будет выполнено переключение процессов для запуска требующегося потока. В приложении с тесно связанными потоками такие переключения существенно снижают производительность. Одновременное планирование сотрудничающих потоков может также сохранить время на выделение ресурсов. Например, ряд потоков при бригадном планировании может обращаться к файлу без дополнительных расходов на блокирование в процессе операций чтения/записи или позиционирования в файле.
Использование бригадного планирования выдвигает требования по распределению процессоров. Предположим, что у нас имеется N процессоров и М приложений, каждое из которых состоит из N или меньшего числа потоков. Тогда каждое приложение при использовании квантования времени может получить 1/M доступного времени N процессоров. В [FEIT90a] замечено, что такая стратегия может оказаться неэффективной. Рассмотрим пример, в котором имеются два приложения, одно с четырьмя потоками, а второе — с одним. Использование равномерного распределения времени приводит к потере 37.5% вычислительного ресурса, поскольку при выполнении однопоточного приложения три процессора простаивают (см. рис. 10.2). При наличии ряда однопоточных приложений они могут распределяться совместно для увеличения загрузки процессоров. Если это невозможно, вторым решением может стать применение взвешенного планирования с учетом количества потоков каждого процесса. В этом случае приложение с четырьмя потоками из нашего примера может занять 80% (4/5) всего времени, а однопоточное — только 20% (1/5), что приведет к снижению потерь вычислительного ресурса до 15%.
Назначение процессоров
Крайней формой бригадного планирования является предложенное в [TUCK89] назначение приложению групп процессоров на все время работы данного приложения. Таким образом, когда приложение спланировано, каждый из его потоков назначается определенному процессору, на котором он и выполняется до завершения работы данного приложения.
Такой подход представляется очень неэффективным в плане процессорного времени. Если поток приложения блокируется операцией ввода-вывода или необходимостью синхронизации с другим потоком, то процессор этого потока простаивает: многозадачность процессора в этом методе отсутствует. В защиту данной стратегии можно привести два соображения,
1. В высокопараллельной системе с десятками или сотнями процессоров, каждый из которых представляет собой лишь малую часть стоимости системы, загруженность процессора не так важна, как общая эффективность или производительность.
2. Полное устранение переключений процессов во время работы программы должно существенно повысить ее скорость работы.
В работах [TUCK89, ZAH090] подтверждено второе высказывание. На рис. 10.3 показаны результаты экспериментов из [TUCK89]. Авторы запускали два приложения (умножение матриц и быстрое преобразование Фурье) в системе с 16 процессорами. Каждое приложение разбивало свою задачу на ряд заданий, которые реализовывались потоками в пределах данного приложения. Программы были написаны таким образом, что позволяли варьировать количество используемых потоков. По существу, количество заданий определялось самим приложением. Если потоков оказывалось меньше, чем заданий, последние ставились в очередь и изымались из нее потоками, завершившими свои задания. Понятно, что далеко не все приложения можно структурировать подобным образом, но многие вычислительные задачи и ряд других приложений вполне могут быть преобразованы таким образом.
На рис. 10.3 показано ускорение работы приложений как функция от количества используемых потоков (которое в каждом приложении варьировалось от 1 до 24). Например, если оба приложения с 24 потоками каждое запускались одновременно, то ускорение их работы по сравнению с однопоточными приложениями составляло 2.8 для быстрого преобразования Фурье и 2.4 — для умножения матриц. На рисунке видно, что производительность обоих приложений снижается при количестве потоков, превышающем 8, и что максимальная производительность достигается тогда, когда общее количество потоков равно количеству процессоров. Большее количество потоков снижает производительность за счет необходимости вытеснения потоков и дополнительных операций планирования. Снижение эффективности при этом определяется целым рядом факторов — от времени, затрачиваемого на ожидание, когда приостановленный поток покинет критический раздел, до снижения эффективности кэшей и времени, затраченного на переключение процессов.
Авторы приходят к выводу, что эффективная стратегия состоит в ограничении общего количества активных потоков в системе количеством процессоров. Если большинство приложений либо однопоточные, либо могут использовать очереди заданий, то такая стратегия обеспечивает эффективное использование процессоров.
Как стратегия назначения процессоров, так и бригадное планирование решают задачу планирования путем распределения процессоров. Однако можно заметить, что распределение процессоров в многопроцессорной системе гораздо больше похоже на задачу распределения памяти в однопроцессорной системе, чем на задачу планирования в однопроцессорной системе. Вопрос о том, сколько процессоров могут быть привлечены к выполнению приложения в конкретный момент времени, аналогичен вопросу о том, сколько кадров страниц может быть предоставлено данному процессу в некоторый момент времени. В [GEHR87] предложен термин рабочее множество активности (activity working set), аналогичный рабочему множеству виртуальной памяти, как минимальное количество единиц активности, которое должно быть одновременно распланировано между процессорами для приемлемого выполнения приложения. Как и в схемах управления памятью, ошибки в планировании элементов рабочего множества активности могут привести к снижению пропускной способности процессора. Это происходит в тех случаях, когда запускаются потоки, обслуживание которых вызывает приостановку других потоков, чьи услуги понадобятся в ближайшее время. Аналогично, фрагментация процессоров означает ситуацию, когда ряд процессоров оказываются распределенными, а оставшихся процессоров либо недостаточно, либо они не соответствуют требованиям ожидающего приложения. Бригадное планирование и распределение процессоров предназначено для устранения таких проблем.
Динамическое планирование
В ряде приложений количество потоков динамически изменяется в процессе их работы, что заставляет операционную систему изменять распределение во время работы приложения.
В [ZAH090] предложен подход, в котором в планирование вовлекаются как операционная система, так и само приложение. Операционная система отвечает за распределение процессоров между задачами. Каждая задача использует выделенные ей в настоящий момент процессоры для выполнения некоторого подмножества доступных в настоящий момент для выполнения заданий, распределяя их по потокам. Принятие решения о выделении такого подмножества для работы, как и о том, какой поток должен быть приостановлен при вытеснении процесса, выполняют отдельные приложения (возможно, посредством множества подпрограмм библиотеки времени исполнения). Такой подход применим не для всех приложений, однако возможна ситуация, когда некоторые приложения будут работать, как однопоточные, в то время как другие приложения изначально будут создаваться с использованием этой возможности операционной системы.
При таком подходе ответственность операционной системы за планирование ограничена распределением процессоров и выполняется в соответствии с изложенными далее принципами. Когда задача требует один или несколько процессоров (неважно, в момент ли поступления в систему или в связи с изменившимися требованиями), происходит следующее.
1. Если в системе имеются простаивающие процессоры, они используются для удовлетворения этого запроса.
2. В противном случае, если запрос подается вновь поступившей в систему задачей, ей выделяется единственный процессор, забираемый у задачи, которая в настоящий момент использует более одного процессора.
3. Если какая-то часть запроса не может быть удовлетворена, он остается невыполненным до тех пор, пока либо не появится свободный процессор, либо задача не снимет свой запрос (например, ей больше не требуется лишний процессор).
4. При освобождении одного или нескольких процессоров сканируется текущая очередь не удовлетворенных запросов на процессоры. Каждому заданию в списке, до сих пор не имеющему ни одного процессора (т.е. ожидающему поступления в систему), назначается по одному процессору. После этого, при наличии свободных процессоров, список сканируется вновь, распределяя оставшиеся процессы на основе стратегии FCFS. Анализ работ [ZAH090, MAJU88] дает основания полагать, что для приложений, которые могут использовать достоинства динамического планирования, этот подход предпочтительнее бригадного планирования или назначения процессоров. Однако накладные расходы при описываемом подходе могут свести на нет получаемые преимущества, и для доказательства превосходства динамического планирования требуется опыт работы реальных операционных систем.
