Как уже говорилось, относительно большие накладные расходы, связанные
с обработкой прерываний, нередко делают целесообразным включение в систему
дополнительных процессоров. Есть и другие доводы в пользу создания многопроцессорных
вычислительных систем.
Одним из доводов является повышение надежности вычислительной системы
посредством многократного резервирования. Если один из процессоров многопроцессорной
системы отказывает, система может перераспределить загрузку между оставшимися.
Для компьютеров первых поколений, у которых наработка аппаратуры процессора
на отказ была относительно невелика, повышение надежности таким способом
часто оказывалось целесообразным, особенно в приложениях, требовавших
круглосуточной доступности.
Примечание
Понятно, что для обеспечения непрерывной доступности недостаточно просто
поставить много процессоров, и даже недостаточно уметь своевременно обнаружить
отказ и исключить сломавшийся процессор из системы. Необходима также возможность
заменить отказавший узел без выключения и без перезагрузки системы, что
накладывает весьма жесткие требования и на конструкцию корпуса, и на электрические
Другим доводом в пользу включения в систему дополнительных процессоров
является тот факт, что алгоритмы, используемые для решения многих прикладных
задач, нередко поддаются распараллеливанию:
разделению работы между несколькими более или менее независимо работающими
процессорами. В зависимости от алгоритма (и, косвенно, от природы решаемой
задачи) уровень достижимого параллелизма может сильно различаться. Отношение
производительности системы к количеству процессоров и производительности
однопроцессорной машины называют коэффициентом масштабирования.
Для различных задач, алгоритмов, ОС и аппаратных архитектур этот коэффициент
различен, но всегда меньше единицы и всегда убывает по мере увеличения
количества процессоров.
Некоторые задачи, например, построение фотореалистичных изображений методом
трассировки лучей, взлом шифров полным перебором пространства ключей [www.distributed.net]
или поиск внеземных цивилизаций [www.seti.org]
поддаются масштабированию очень хорошо: можно включить в работу десятки
и сотни тысяч процессоров, передавая при этом между ними относительно
малые объемы данных. В этих случаях часто оказывается Целесообразно даже
не устанавливать процессоры в одну машину, а использовать множество отдельных
компьютеров, соединенных относительно низкоскоростными каналами передачи
данных. Это позволяет задействовать процессоры, подключенные к сети (например,
к Интернет) и не занятые в данный момент другой полезной работой.
Другие задачи, например, работа с базами данных, поддаются распараллеливанию
в гораздо меньшей степени, однако и в этом случае обработка запросов может
быть распределена между несколькими параллельно работающими процессорами.
Количество процессоров в серверах СУБД обычно измеряется несколькими штуками,
они подключены к обшей шине, совместно используют одну и ту же оперативную
память и внешние устройства.
Многопроцессорность в таких системах обычно применяется только для ц0.
вышения производительности, но очевидно, что ее же можно использовать
и для повышения надежности: когда функционируют все процессоры, система
работает быстро, а с частью процессоров работает хоть что-то, пусть и
медленнее.
Некоторые многопроцессорные системы поддерживают исполнение на ных процессорах
различных ОС — так, на IBM z90 часть процессоров M исполнять Linux, а
остальные — z/OS. В такой конфигурации, работающий под управлением Linux
Web-сервер может взаимодействовать с работающим под z/OS сервером транзакций
через общую физическую память. Многопроцессорные серверы Sun Fire могут
исполнять несколько копий Solaris.
Промежуточное положение между этими крайностями занимают специализированные
массивно-параллельные компьютеры, используемые
для таких задач, как численное решение эллиптических дифференциальных
уравнений и численное же моделирование методом конечных элементов в геофизических,
метеорологических и некоторых других приложениях.
Современные суперкомпьютеры этого типа (IBM „SP6000, Cray Origin) состоят
из десятков, сотен, а иногда и тысяч отдельных процессорных модулей (каждый
модуль представляет собой относительно самостоятельную вычислительную
систему, обычно многопроцессорную, с собственной памятью и, нередко, с
собственной дисковой подсистемой), соединенных между собой высокоскоростными
каналами. Именно к этому типу относился шахматный суперкомпьютер Deep
Blue, выигравший в 1997 году матч у чемпиона мира по шахматам Гарри Каспарова
[www.research.ibm.com].
Многопроцессорные системы различного рода получают все более и более широкое
распространение. Если производительность отдельного процессора удваивается
в среднем каждые полтора года ("закон Мура" [www.intel.com
Moore]), то производительность многопроцессорных систем удваивается
каждые десять месяцев [www.sun.com 2001-05].
На практике, даже хорошо распараллеливаемые алгоритмы практически никогда
не обеспечивают линейного роста производительности с ростом числа процессоров.
Это обусловлено, прежде всего, расходами вычислительных ресурсов на обмен
информацией между параллельно исполняемыми потоками. На первый взгляд,
проще всего осуществляется такой обмен в системах с процессорами, имеющими
общую память, т. е. собственно многопроцессорных компьютерах.
В действительности, оперативная память имеет конечную, и небольшую по
сравнению с циклом центрального процессора, скорость доступа. Даже один
современный процессор легко может занять все циклы доступа ОЗУ, а несколько
процессоров будут непроизводительно тратить время, ожидая доступа к памяти.
Многопортовое ОЗУ могло бы решить эту проблему,
но такая память намного дороже обычной, однопортовой, и применяется лишь
в особых случаях и в небольших объемах.
Одно из основных решений, позволяющих согласовать скорости ЦПУ и ОЗУ,
— это снабжение процессоров высокоскоростными кэшами
команд и данных. Такие кэши нередко делают не только для центральных
процессоров, но и для адаптеров шин внешних устройств. Это значительно
уменьшает количество обращений к ОЗУ, однако мешает решению задачи, ради
которой мы и объединяли процессоры в единую систему: обмена данными между
потоками, исполняющимися на разных процессорах (рис. 6.2).
Рис. 6.2. Некогерентный кэш
Большинство контроллеров кэшей современных процессоров предоставляют
средства обеспечения когерентности кэша —
синхронизацию содержимого кэш-памятей нескольких процессоров без обязательной
записи данных в основное ОЗУ.
Суперскалярные процессоры, у которых порядок реального исполнения операций
может не совпадать с порядком, в котором соответствующие команды следуют
в программе, дополнительно усугубляют проблему.
Порядок доступа к памяти в SPARC
Современные процессоры предоставляют возможность управлять порядком доступа
команд к памяти. Например, у микропроцессоров SPARCvQ [www.sparc.com v9]
определены три режима работы с памятью (модели памяти), переключаемые
битами в статусном регистре процессора.
Свободный доступ к памяти (RMO, Relaxed Memory Order), когда процессор
использует все средства кэширования и динамического переупорядочения команд,
и не пытается обеспечить никаких требований к упорядоченности выбор-ки
и сохранению операндов в основной памяти.
Частично упорядоченный доступ (PSO, Partial Store Order), когда процессор
по-прежнему использует и кэширование, и переупорядочивание, но в потоке
команд могут встречаться команды MEMBAR. Встретив такую команду, сор обязан
гарантировать, что все операции чтения и записи из памяти, зако дированные
до этой команды, будут исполнены (в данном случае под исполнением подразумевается
перенос результатов всех операций из кэша в ОЗУ), д0 того, как процессор
попытается произвести любую из операций доступа к памяти, следующих за
MEMBAR.
Полностью упорядоченный доступ (TSO, Total Store Order), когда процессор
гарантирует, что операции доступа к памяти будут обращаться к основному
ОЗУ в точности в том порядке, в котором закодированы.
Каждый следующий режим повышает уверенность программиста в том, что его
программа прочитает из памяти именно то, что туда записал другой процессор,
но одновременно приводит и к падению производительности. Наибольший проигрыш
обеспечивает наивная реализация режима TSO, когда мы просто выключаем
и динамическое переупорядочение команд, и кэширование данных (кэширование
кода можно оставить, если только мы не пытаемся исполнить код, который
подвергается параллельной модификации другим задатчиком шины).
Другим узким местом многопроцессорных систем является системная шина. Современные компьютеры общего назначения, как правило, имеют шинную архитектуру, т. е. и процессоры, и ОЗУ, и адаптеры шин внешних устройств (PCI и т. д.) соединены общей магистралью данных, системной шиной или системной магистралью. В каждый момент магистраль может занимать только пара устройств, задатчик и ведомый (рис. 6.3). Обычно, задатчиком служит процессор — как центральный, так и канальный — или контроллер ПДП, а ведомым может быть память или периферийное устройство. При синхронизации содержимого кэшей процессорный модуль также может оказаться в роли ведомого.
Рис. 6.3. Шинная архитектура
Доступ к шине регулируется арбитром шины.
Практически применяются две основные стратегии арбитража — приоритетная,
когда устройство, имеющее высокий приоритет, всегда получает доступ, в
том числе и при наличии запросов от низкоприоритетных устройств, и
справедливая (fair), когда арбитр гарантирует всем устройствам
доступ к шине в течение некоторого количества циклов.
Системы шинной архитектуры просты в проектировании и реализации, к ним
легко подключать новые устройства и типы устройств, поэтому такая архитектура
получила широкое распространение. Однако, особенно в многопроцессорных
системах, шина часто является одним из основных ограничителей производительности.
Повышение пропускной способности шины зачастую возможно, но приводит к
повышению обшей стоимости системы.
Впрочем, при большом количестве узлов проблемы возникают и у систем со
столь высокоскоростной шиной, как FirePane. Кроме того, по мере роста
физических размеров системы, становится необходимо принимать во внимание
физическую скорость передачи сигналов — как сигналов самой магистрали,
так и запросов к арбитру шины и его ответов. Поэтому шинная топология
соединений при многих десятках и сотнях узлов оказывается .неприемлема,
и применяются более сложные топологии.
Системы NUMA-Q
Многопроцессорные серверы IBM NUMA-Q состоят из отдельных процессорных
модулей. Каждый модуль имеет собственную оперативную память и четыре процессора
х86. Модули называются quad (четверки) (рис. 6.4).
Четверки соединены высокоскоростными каналами IQ-Link с центральным коммутатором.
Замена общей шины на звездообразную топологию с центральным коммутатором
позволяет решить проблемы арбитража доступа к шине, в частности, устранить
задержки при запросе к арбитру шины и ожидании его ответа запрашивающему
устройству. NUMA-системы фирмы IBM могут содержать до 16 четверок, т.
е. до 64 процессоров.
Архитектура позволяет также включать в эти системы процессоры с архитектурой,
отличной от х86, например RS/6000 и System/390, позволяя, таким образом,
создать в пределах одной машины гетерогенную сеть со сверхвысокоскоростными
каналами связи.
При большем числе модулей применяются еще более сложные топологии, например
гиперкубическая. В таких системах каждый узел
обычно также содержит несколько процессоров и собственную оперативную
память (рис. 6.5).
При гиперкубическом соединении, количество узлов N пропорционально степени
двойки, а каждый узел имеет log2N соединений с другими узлами.
Каждый узел способен не только обмениваться сообщениями с непосредственными
соседями по топологии, но и маршрутизировать сообщения между узлами, не
имеющими прямого соединения. Самый длинный путь между узлами, находящимися
в противоположных вершинах куба, имеет длину log2N и не является
единственным (рис. 6.6). Благодаря множественности путей, маршрутизаторы
могут выбирать для каждого сообщения наименее загруженный в данный момент
путь или обходить отказавшие узлы.
Рис. 6.4. NUMA-Q с тремя четырехпроцессорными модулями
Массивно параллельные системы Cray/SGI
Origin
Узлы суперкомпьютеров семейства Cray/SGI Origin соединены в гиперкуб каналами
с пропускной способностью 1 Гбайт/с. Адаптеры соединений обеспечивают
не просто обмен данными, а прозрачный (хотя и с падением производительности)
доступ процессоров каждого из узлов к оперативной памяти других узлов
и обеспечение когерентности процессорных кэшей.
Рис. 6.5. Гиперкубы с 4, 8 и 16-ю вершинами
Различие в скорости доступа к локальной памяти процессорного модуля и Других модулей является проблемой, и при неудачном распределении загрузки между модулями (таком, что межмодульные обращения будут часты) Приведет к значительному снижению производительности системы. Известны два основных пути смягчения этой проблемы.
Рис. 6.6. Самый длинный путь в гиперкубе
Понятно, что обе эти архитектуры не решают в корне проблемы неоднородности
доступа: для обеих можно построить такую последовательность межпроцессорных
взаимодействий, которая промоет1 все кэши и перегрузит межмодульные связи,
а в случае СОМА приведет к постоянной перекачке страниц памяти между модулями.
То же самое, впрочем, справедливо и для симметричных многопроцессорных
систем с общей шиной.
В качестве резюме можно лишь подчеркнуть, что масштабируемость
(отношение производительности системы к количеству процессоров) многопроцессорных
систем определяется в первую очередь природой задачи и уровнем параллелизма,
заложенным в использованный для решения этой задачи алгоритм. Разные типы
многопроцессорных систем и разные топологии межпроцессорных соединений
пригодны и оптимальны для различных задач.
Промывание кэша— довольно распространенный термин. Это последовательность
обращении, которая намного больше объема кэша и в которой нет ни одного
повторного обращения к одной и той же странице, или очень мало таких обращении.