Многоядерность: миф или реальность?


PDF версия

В статье рассматривается развитие процессоров и памяти начиная с 1980-х гг., описываются проблемы создания систем на базе современных ЦП, анализируются преимущества использования многоядерных процессоров и даются практические рекомендации для разработчиков, в т.ч. и встраиваемых систем.

В течение многих лет быстродействие процессоров и памяти развивалось одновременно. Ранние ЦП, например Z80, требовали выполнения определенного числа машинных циклов, даже за счет пустых команд. При обычных для того времени тактовых частотах в несколько мегагерц скорость процессора точно соответствовала временным циклам электрически стираемого программируемого ПЗУ (EPROM) и статической оперативной памяти с произвольным доступом (SRAM).
Однако со временем скорость памяти превысила производительность ЦП. Процессоры 8088/6 имели устройство предвыборки, чтобы подстроить быструю память под медленный процессор. Очень небольшая (4…6 байт) очередь FIFO (First In, First Out) изолировала ядро от блока шинного интерфейса BIU (Buffer Interface Unit), который был свободен для предварительной выборки наиболее вероятной следующей команды, если ядро было занято выполнением какой-то операции, не требовавшей участия шины. Таким образом, блок шинного интерфейса помог поддержать приемлемое соответствие скоростей ЦП и памяти.
Даже к концу 1980-х гг. процессоры были вполне хорошо согласованы с памятью. 386-й процессор, который, с точки зрения программиста (за исключением инструкций работы с плавающей точкой), очень схож с последними высокотехнологичными предложениями фирмы Intel, работал на частоте 16 МГц. Таким образом, трехцикловая пустая команда длилась 188 нс, что хорошо соотносилось с большинством устройств памяти с нулевым ожиданием.
Однако тактовые частоты ЦП продолжили расти, в то время как быстродействие памяти начало отставать. 386-й процессор имел тактовую частоту 40, а 486-й — свыше 100 МГц. Некоторые основные положения архитектуры с уменьшенным набором команд (RISC), в особенности выполнение команд за один цикл, были приняты на вооружение сторонниками CISC-архитектуры, что еще больше усилило несоответствие.
Производители воспользовались законом Мура, т.к. стало гораздо легче увеличить число транзисторов в процессорах, чтобы решить проблему недостаточно быстрой памяти. Конвейеры позволили перенести больше команд на кристалл, а дополнительная логика параллельно выполняла части многих инструкций.
Процессор с тактовой частотой 100 МГц и выполнением команды в течение одного цикла выбирает одно слово из памяти каждые 10 нс, но даже сегодня это довольно высокая скорость для оперативной памяти, не говоря уже о флэш-памяти. Таким образом, появилась внутренняя кэш-память, использующая дешевые транзисторы, интегрированные в кристалл. Ее появление, а также работа с плавающей точкой и некоторые другие ухищрения привели к увеличению количества транзисторов в 486-м процессоре более чем в четыре раза по сравнению с 386-м.
В процессорах класса Pentium стали использоваться распараллеленные вычисления задолго до появления частот 2…3 ГГц. Устройства памяти со временем обращения 0,33 нс непрактичны по целому ряду причин, одна из которых — трудноразрешимая задача разводки сигналов между чипами микросхем памяти. Далеко не многие пользователи были бы довольны процессором с частотой 3 ГГц, который тормозился бы всякий раз при чтении или записи памяти, поэтому размеры кэша увеличились еще боль-
ше.
Но даже встроенная в кристалл память с нулевым временем ожидания стоит дорого. По этой причине произошло разделение кэш-памяти на уровни: небольшая по объему и быстрая кэш-память первого уровня (L1), затем более медленная — второго уровня (L2) и, наконец, в некоторых случаях даже кэш-память третьего уровня (L3). К тому же большее число транзисторов привело к усложнению алгоритмов предсказания ветвления, отслеживания кэша и т.д., что явилось следствием желания управлять кэшем и сократиь медленный по своей природе шинный трафик.
Вот уже как 15 лет память гораздо медленнее процессоров и является основным узким местом. Не так давно рост скоростей ЦП прекратился из-за увеличившегося рассеяния мощности. Она рассеивается при коммутации транзистора, а также из-за небольших технологических дефектов, в результате которых через устройство протекают микротоки. Небольшие потери на одном транзисторе многократно увеличиваются в масштабе всего прибора, что приводит к его сильному нагреванию.
Ситуация такова, что огромное число транзисторов в современных процессорах не используется большую часть времени. Постоянно активной остается только одна строка кэш-памяти, тогда как большая часть логики для обработки сотен различных команд простаивает между редкими моментами обращения к ней, и модули трансляции страницы, которые управляют гигабайтами памяти, обрабатывают одно слово в единицу времени.
Эти неактивные транзисторы из-за токов утечки переводят часть энергии в тепло. Идея о непрерывном увеличении количества транзисторов столкнулась с проблемой ограничения мощности рассеяния. Столь ограниченные скорости памяти способствовали созданию чрезвычайно сложных ЦП, но из-за сильного нагрева прекратился рост тактовых частот, который позволял ежегодно создавать более мощные компьютеры.
В мире суперкомпьютеров наблюдалсь схожая картина. Элементная база на основе арсенида галлия и другие экзотические компоненты позволяли достигать высоких частот, а от перегрева машины спасало водяное охлаждение. Однако достаточно давно исследователи осознали тщетность достижения технологических успехов путем увеличения тактовой частоты и начали создавать вычислительные машины параллельного действия. Многие разработчики теперь используют тысячи идентичных функциональных узлов, которые часто организованы на процессорах, предназначенных для обычных настольных компьютеров. Высокая производительность достигается в результате широкомасштабного параллельного решения задач и совершенствования аппаратных средств.
Для повышения быстродействия производители ЦП для настольных ПК создали общую модель суперкомпьютера и предложили многоядерные устройства, которые представляют собой два или более стандартных процессора, расположенных на одном кристалле. В типичную конфигурацию входят два ЦП, у каждого из которых свой кэш L1 и общий кэш L2, который соединяется с внешними устройствами через единую шину. Имеются также встраиваемые варианты таких конфигураций, очень похожие на своих собратьев — ПК.

 

Симметричная многопроцессорная обработка

Симметричная мультипроцессорная обработка (Symmetrical Multi Processing, SMP) определяется несколькими способами. В качестве определения я выбрал проект, в котором множество идентичных процессоров делят одну шину памяти, образуя систему SMP. Таким образом, многоядерные решения от Intel, AMD и некоторых других компаний являются устройствами SMP. SMP-обработка позволит увеличить производительность системы только (в лучшем случае) в той мере, в какой задачу можно распараллелить.
Эмпирический закон Амдала дает численное значение выгоды от использования нескольких процессоров. Его суть в том, что ускорение вычислений, которое достигается за счет распараллеливания операций программы между процессорами, не может превысить значения

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

 

Рис. 1. Зависимость ускорения вычислений от доли нераспараллеливаемых задач

Возникает крайне важный вопрос: какую выгоду можно извлечь из параллелизации вычислительных процессов? По крайней мере, решение части многих задач можно доверить одновременной обработке на нескольких процессорах. Однако большинство задач имеет существенные взаимосвязи между компонентами, которые следует выполнять в определенной последовательности. При выборе процессора трудно понять сразу, насколько выгодно использовать его многоядерность.
Производители многоядерных процессоров наперебой уверяют, что двухъ­ядерные системы повышают производительность на 30—50% (для настольных приложений; как это утверждение соотносится со встраиваемыми системами — совсем другой вопрос, ответ на который зависит от типа приложения). Если рассмотреть наилучшее значение (50%) и вспомнить закон Амдала, то становится ясным — производители считают, что 1/3 программ можно распараллелить. Это значение достигается в самом лучшем случае, т.к. ПК одновременно обрабатывает и другие части приложения и может разделить выполняемые ветви программно. Однако, следуя этой логике и принимая во внимание, что существенное (на 50%) улучшение скорости достигается в случае выполнения одной программы, при неограниченном числе процессоров можно рассчитывать на трехкратное повышение производительности (за исключением особого случая, когда речь идет о параллельных программах).
А теперь поговорим об узком месте — шине.
Каждое из ядер в двухпроцессорном чипе c SMP-обработкой имеет собственный кэш с нулевым временем ожидания доступа, который содержит моментально доступные для процессора инструкции и данные. Но это касается только кэша L1; кэш L2 является общим, достаточно быстрым. Тем не менее он требует нескольких состояний ожидания при каждом обращении. За пределами кэша L2 всего лишь единственная шина служит двум быстродействующим микропроцессорам, которые очень требовательны к циклам работы памяти. Они, в свою очередь, замедлены большим количеством состояний ожидания, что делает тактовую частоту процессора неприменимой для внешней деятельности.
В этом-то вся ирония: многогигагерцовые ЦП, которые могут адресовать гигабайты памяти и имеют десятки миллионов транзисторов, предназначенных для ускорения операций, работают очень быстро только с кэшем L1, чей стандартный микроскопический размер не превышает 32…64 Кбайт. Пара процессоров Z80х справились бы с этим заданием столь же блестяще!
В мире систем управления гораздо большее, чем в ПК, значение имеет выполнение программы в реальном времени. Некоторые фирмы-разработчики нашли интересные решения более эффективного использования фактора многоядерности, например отнесение задач к отдельным ядрам. Я видел несколько удачных воплощений этой идеи. Если задача полностью обходится только кэшем L1 или даже захватывает кэш L2, следует ожидать огромного повышения производительности.
Любая программа, которая то подключается к кэшу, то отключается от него, может пострадать от принципа детерминизма. Как можно говорить о «реальном времени», когда промах кэша увеличивает время выполнения приложения на порядок и более? Понятно, что оно в очень большой степени зависит от использумого приложения, но утверждать при этом, что система реального времени работает детерминированно, в лучшем случае, трудно. Кэш, конвейеры, упреждающее исполнение команд, а теперь еще и двухъядерный ЦП используют ту же медленную шину, что очень усложняет задачу. По определению, жесткая система реального времени, не способная выполнять работу в срок, является такой же недееспособной, как и программа с дефектным кодом.
Многоядерность действительно пытается решить очень важную проблему, а именно — энергопотребление. Некоторые производители подчеркивают, что их продукция имеет показатель свыше 1 MIPS/Вт. Сократите немного частоту ЦП, удвойте число процессоров — и общее энергопотребление резко снизится. При использовании последних моделей ЦП, потребляющих 100 Вт и выше, энергопитание становится трудной проблемой, особенно во встраиваемых системах. Большинство известных методов SMP-обработки все еще энергозатратно и не подходит для многих классов встраиваемых систем.
Важно понять, позволит ли многоядерная технология с архитектурой 386-х процессоров без их прихотливой адресации и других особенностей управления шиной, требующих основательной поддержки со стороны кэша или, по крайней мере, быстрой ОЗУ, достичь лучшего соотношения MIPS/Вт/цена хотя бы в области встраиваемых систем, где гигантские приложения относительно редки?
Наконец, заветной мечтой в использовании архитектуры SMP на протяжении 30 лет является автопараллельный компилятор, который мог бы разделить последовательную задачу между несколькими ядрами. Некоторые успехи в этом направлении уже достигнуты, но многое еще предстоит сделать. Например, во встраиваемых системах эту задачу пытаются решить на уровне ОС. ОСРВ QNX, Green Hills и другие снабжены самыми лучшими инструментальными средствами, позволяющими разделить задачи между ядрами как в статическом, так и в динамическом режимах. Однако возможны другие затруднения, которые усложнят процесс программирования многоядерных систем.

Заключение

Возможно, многим покажется, что эта статья призывает отказаться от технологии многоядерности, однако это совсем не так. Мне хотелось рассеять те страхи, которые сопровождают появление многоядерных процессоров, что обычно бывает при появлении любой новой технологии. Многоядерные процессоры уже получили широкое распространение, они действительно обладают некоторыми важными преимуществами, обеспечивающими внушительный рост производительности с помощью архитектуры SMP [1]. Большинство за-
труднений разрешается, если каждое ядро обрабатывает код из своей области памяти. Некоторые клиенты фирмы Tensilica получают потрясающий при-рост производительности с помощью этой технологии. Также внушительны результаты компании Pichochip [2]. Однако в последнем примере не ис­пользуется архитектура SMP.
Как и всегда, требуется тщательно анализировать свои конкретные потребности перед серьезным переходом на новую технологию.

 

Литература

Оставьте отзыв

Ваш емейл адрес не будет опубликован. Обязательные поля отмечены *