На протяжении длительного времени прогресс в области микропроцессоров фактически отождествлялся со значением тактовой частоты. В 2001 году в корпоративных планах производителей микропроцессоров значилось, что уже к концу десятилетия будет преодолен барьер 10 ГГц. Увы, планы эти оказались неверны. Прав же оказался тот, кто сделал ставку на многоядерные архитектуры.
Первый двухъядерный процессор в семействе Power выпустила корпорация IBM. Сегодня многоядерные процессоры предлагает Sun Microsystems (восьмиядерный UltraSPARC T1), а также Intel и AMD. Однако, несмотря на видимый подъем интереса к многоядерным и многопотоковым процессорам, следует признать, что ключевой момент грядущей «параллельной революции» заключается не в собственно процессорах, а в грядущих радикальных изменениях в программном обеспечении. Оно должно стать таким, чтобы сохранилась возможность использовать преимущества экспоненциального роста производительности процессоров.
Сила есть — ума не надо
На протяжении многих лет разработка суперкомпьютеров была авангардом ИТ-индустрии, своего рода полигоном, где отрабатывались перспективные решения, которые потом переносились на тиражируемые компьютерные системы. Но лет 20-25 тому назад пути массовых систем и суперкомпьютеров разошлись, что не пошло на пользу ни тем, ни другим. Надо признать, что с архитектурной точки зрения нынешние суперкомпьютеры упростились до банальных кластеров, собрать которые мог кто и где угодно — хоть в доме пионеров, были бы место и средства. Однако в последние годы ситуация меняется; пути развития массовых компьютеров и суперкомпьютеров снова сближаются. Причиной тому явление, получившее название Concurrency Revolution. Что можно перевести как «параллельная революция», хотя английское понятие concurrency сложнее, чем «параллельность», поскольку выражает не тривиальный «геометрический» параллелизм, а одновременное существование во времени и пространстве, взаимную совместимость.
В расхождении траекторий развития суперкомпьютеров и остальных компьютерных систем оказалось «виновато» быстрое развитие микропроцессорных технологий. Благодаря микропроцессорам практически вся логика компьютеров оказалась собранной на одном кристалле. Из-за этого архитектура компьютеров со времен мини-ЭВМ пребывала в стагнации; их конструирование превратилось в игру в кубики (чтобы убедиться в этом, достаточно посмотреть на любое из семейств современных серверов). К тому же на протяжении десятилетий количественные показатели микропроцессоров росли так быстро, что уверенность в истинности выбранного направления превратилась в догму. Размножились различные формулировки, ошибочно трактующие закон Мура (среди них — утверждения, будто частота или даже производительность удваиваются каждые два года; на самом деле гениальное предвидение одного из основателей Intel фиксирует периодическое удвоение количества транзисторов на кристалле).
Бурное развитие микроэлектроники всегда однозначно воспринималось только со знаком плюс. Действительно, результаты прогресса видны невооруженным взглядом, но у любого явления всегда есть оборотная сторона; развитие по закону Мура — не исключение. Из-за удельного удешевления транзисторов открылась возможность компенсировать несовершенство процессорной архитектуры их количеством, что в конечном итоге и стало причиной консервации предложенной в далекие 40-е годы схемы организации компьютерных систем, которая получила свое название по имени Джона фон Неймана. Трудно представить еще какую-либо из современных технологических областей, которая, декларируя свою причастность к техническому прогрессу, была бы столь консервативна по своей сути. О врожденных недостатках фон-неймановской схемы написано немало, но, что бы сейчас ни говорили на эту тему, еще лет десять назад никакие аргументы не возможно было противопоставить убеждению в том, что процессорная индустрия выбрала единственно правильный путь, основанный на количественном росте. Достаточно вспомнить, с какой гордостью произносились новые цифры; считалось, что, если не хватит миллиона транзисторов, сделаем миллиард — «нет проблем», главное уменьшить размеры кристаллов и межсоединений и повысить тактовую частоту. Но за все приходится платить. Каждый транзистор потребляет энергию, в итоге, по данным IDC, сегодня затраты на электричество, необходимое для питания центров обработки данных, составляют свыше 80% от затрат на приобретение компьютерного оборудования, а через пару лет эти показатели сравняются.
Модернизации схемы фон Неймана
В культовом убеждении в незыблемости первооснов выросли поколения специалистов, если называть вещи своими именами, воспроизводивших классическую модель фон Неймана с небольшими видоизменениями. На самом деле фон-неймановская архитектура компьютера не является единственно возможной, пространство допустимых решений гораздо шире. Так, исходя из способов организации последовательности выполнения команд и обмена данными между процессором и памятью, все компьютеры можно разделить на четыре класса:
-
SISD (Single Instruction Single Data) — «один поток команд, один поток данных»;
-
SIMD (Single Instruction Multiple Data) — «один поток команд, много потоков данных»;
-
MISD (Multiple Instruction Single Data) — «много потоков команд, один поток данных»;
-
MIMD (Multiple Instruction Multiple Data) — «много потоков команд, много потоков данных».
Класс SISD предполагает, что в один момент времени может быть выполнена одна команда, и она может оперировать только теми порциями данными, адреса которых непосредственным образом присутствуют в операндах этой команды. Напротив, в класс MIMD попадают машины, которые могут одновременно выполнять множество команд, используя при этом множество фрагментов данных. Эта классификация известна как «таксономия Флинна», она названа так по имени предложившего ее Майкла Флинна, выдающегося инженера и ученого, ныне являющегося профессором Стэндфордского университета. Из нее следует, что фон-неймановская машина является частным случаем, попадающим в класс SISD. Большинство современных компьютеров построено именно по этой схеме; между тем все суперкомпьютеры из первой десятки TOP500 построены по схеме MIMD.
Было бы некорректно объяснять рост производительности процессоров только наращиванием количественных показателей, вполне естественно, что на протяжении десятилетий было предложено несколько серьезных модернизаций, являющихся отступлениями от схемы фон Неймана, но ограниченными масштабом. Исторически первым оказалось изобретение процессоров, способных выполнять операции не над содержимым одного или нескольких регистров, а над более крупными фрагментами данных; по классификации Флинна они попадают в класс SIMD. Их появление связывают с проектом Solomon (1962 год, компания Westinghouse). Позднее аналогичный принцип работы с данными был реализован в самой производительной машине своего времени ILLIAC IV (1972). Если процессор, используя одну команду, может выполнять действия над векторами, то его называют векторным процессором (vector processor), а если над массивами, то процессором массивов (array processor). Впоследствии Сеймур Крей использовал векторные принципы при разработке своих суперкомпьютеров, начиная с Cray-1. Сегодня схема SIMD широко используется в специализированных процессорах, предназначенных для игровых консолей.
После введения нового класса векторных процессоров обычные процессоры стали вынужденно, чтобы различать, называть «скалярными»; именно поэтому на следующем шаге появились решения со странным названием «суперскалярные процессоры». Идея суперскалярности заключается в том, что процессор просматривает приближающиеся к исполнению команды и выбирает из них те последовательности, которые могут быть выполнены параллельно. Такие процессоры способны выполнять несколько инструкций за один такт, а такой вид параллелизма стали называть параллелизмом на уровне команд (Instruction-Level Parallelism, ILP). Очевидно, что при заданной частоте суперскалярный процессор будет производительнее скалярного, поскольку он способен выделить в подмножество и одновременно выполнить несколько команд, распределив их по своим функциональным устройствам. Родоначальником идеи ILP был тот же Крей; он реализовал ее в 1965 году в компьютере CDC 6600, затем ILP была воспроизведена в процессоры Intel i960 (1988 год) и AMD 29050 (1990), особенно «впору» суперскалярный подход пришелся для RISC-процессоров с их упрощенной системой команд. Позже, начиная с Pentium II, обрели ILP и процессоры с архитектурой CISC.
Примерно в то же время — сначала на мэйнфреймах, а позже и на мини-ЭВМ — появилась кэш-память; в дальнейшем идея кэширования получила развитие в многоуровневых решениях, предполагавших наличие кэшей первого и второго, а затем и третьего уровня.
Еще одним существенным изобретением, ускорившим работу процессоров, оказалось внеочередное исполнение (out-of-order execution, OoO), представляющее собой ограниченную реализацию идеи обработки потока данных (data flow computation). Хотя первые попытки в этом направлении были предприняты еще при проектировании компьютеров CDC, но реально первые внедрения были в IBM 360, а затем в процессорах Power1. Одно из важнейших достоинств внеочередного исполнения состоит в том, что данная технология позволяет согласовать более высокую скорость работы процессоров с менее быстродействующей памятью, сняв часть нагрузки с кэш-памяти.
Заметной вехой в ряду усовершенствований фон-неймановской архитектуры стоит распараллеливание потоков (Thread Level Parallelism, TLP). Данная технология существует в нескольких версиях; среди них — одновременная многопоточность (Simultaneous Multithreading, SMT) и многопоточность на уровне кристалла (Сhip-level Multithreading, CMT). Эти два подхода в основном различаются представлением о том, что есть «поток», иначе говоря, по уровню гранулярности потоков. Хронологически первым процессором, поддерживающим многопоточность, был процессор DEC Alpha EV4 21064. Драматическая судьба этого процессорного семейства была и остается предметом серьезных обсуждений, и, хотя на версии EV7 производство прекратилось, а EV8 и EV9 остались на бумаге, есть основания полагать, что ядро EV7 может возродиться в одном из готовящихся к выпуску многоядерных процессоров. Типичным представителем лагеря SMT является Pentium 4 с его технологией HTT (Hyper-Threading Technology). Процессор поддерживает деление на два потока команд, выбираемых из одной задачи в режиме SMT, что обеспечивает суммарное повышение производительности примерно на 30%. В процессоре UltraSPARC T1, известном прежде под кодовым названием Niagara, потоки образуются из разных задач; никакой одновременности в данном случае нет, каждый поток представляет собой виртуальное ядро процессора.
Итак, все вроде бы замечательно, но результатом усложнения логики оказалась заметная диспропорция в затратах на производительную и вспомогательную составляющие процессоров — собственно арифметико-логическое устройство занимает на них менее 20% площади кристалла.
Ядра на кристалле
Первыми представителями архитектуры CMP стали процессоры, предназначенные для использования в серверах, это был простой тандем, в таких приборах на одной подложке размещаются два, по сути, независимых ядра (рис. 1, б). Помимо экономии места подобное решение дает ощутимую экономию энергии, поскольку часть системотехнических компонентов является общей для обоих ядер. Развитием этой схемы стали решения CMP, показанные на рис. 1, в и 1, г. Сначала исходная идея обогатилась общей кэш-памятью, а затем каждое из ядер стало многопотоковым; каждое из этих усовершенствований увеличивает те преимущества, которые дает совмещение нескольких ядер в одном кристалле. Но нельзя забывать и о том, что деление процессора на ядра и далее на потоки внутри ядер, и как любое иное инженерное решение, не свободно от необходимости идти на компромисс. Разумеется, в перспективе оно может обеспечить целый ряд преимуществ, но, чтобы их получить, необходимо преодолеть весьма серьезные препятствия. Однако прежде о достоинствах.
С точки зрения организации и упрощения проектирования достоинства CMP неоспоримы. Понятно, можно разработать одно очень эффективное ядро, а затем тиражировать его в нужном количестве, дополняя архитектуру нужными системными компонентами. Такой подход обладает модульностью, масштабируемостью, а главное, уменьшает трудозатраты, что сможет в будущем изменить баланс сил на процессорном рынке. Дело в том, что увеличение количества транзисторов в одном ядре ведет к резкому, нелинейному росту затрат труда проектировщиков и других специалистов, участвующих в процессе создания новых кристаллов. Как следствие, возрастает стоимость проектирования новых процессоров, а потому этот вид деятельности становится прерогативой самых крупных компаний. (Одно время, когда практически все поверили в архитектуру EPIC, многим представлялось, что число семейств процессоров вообще будет сведено к одному или — в крайнем случае — к двум; к счастью, эти прогнозы не оправдались.) При модульном проектировании трудозатраты оказываются существенно меньше, чем затраты на проектирование единого, существенно более сложного процессорного ядра. Как следствие, переход к многоядерным архитектурам может демократизировать процессорную отрасль; он в состоянии вернуть на рынок небольшие компании и создать новые возможности для возникновения разнообразных «стартапов». В этом отношении показателен пример Sun Microsystems, которая открыла спецификацию на процессор Ultra SPARC T1, и уже сегодня появились компании, воспроизводящие его архитектуру в собственных разработках. Схожие цели преследует и корпорация IBM, инициировавшая создание и поддерживающая деятельность сообщества power.org.
Второе преимущество заключается в том, что переход на многоядерные процессоры позволит решить постоянно возрастающие проблемы энергопотребления. Вообще говоря, то, что центры обработки данных, имеющие дело с нематериальной сферой, сравнились по уровню энергопотребления с промышленными производствами, выглядит, по меньшей мере, странно. Если, к примеру, на кристалле разместить два ядра и заставить их работать на тактовой частоте, вдвое меньшей, чем аналогичный одноядерный процессор, а потом сравнить энергопотребление этого кристалла с монолитным аналогом, имеющим производительность, равную их суммарной характеристике, то обнаружится, что энергопотребление уменьшается в несколько раз, поскольку оно растет почти пропорционально квадрату частоты. Для оценки этого рода преимуществ многоядерных процессоров в Sun предложили метрику SWaP (Space, Watts and Performance), которая выражается отношением производительности к произведению потребляемой мощности на занимаемое пространство. По этой метрике серверы, построенные на процессорах Niagara, превосходят свои аналоги в пять с лишним раз. Это абсолютный и не нуждающийся в комментариях аргумент в пользу многоядерности.
И тем не менее в этом эффективном сравнении есть очевидная некорректность, основной вопрос заключается в том, что именно понимать под производительностью. Напрашивается очевидная аналогия с автомобильными двигателями. Для того чтобы адекватно оценить характеристики двигателя внутреннего сгорания, одним показателем — его максимальной мощностью обойтись нельзя. Следует учитывать то, на каком числе оборотов развивается максимальная мощность, какова максимальная величина крутящего момента и какова моментная характеристика. Следуя методике Sun, мы можем предложить условный показатель, аналогичной SWaP, включив в него вес, мощность, расход топлива и что-то еще в этом роде. После этого мы будем сравнивать, скажем, двигатели легкового автомобиля с судовыми или тепловозными двигателями, в таком случае при равной мощности десять двигателей по 200 лошадиных сил опередят тяжелый дизель по этому показателю в десятки раз, но это вовсе не значит, что они смогут обеспечить адекватную замену. Двигателю от болида «Формулы-1» не удастся сдвинуть с места железнодорожный состав.
Примерно то же самое можно сказать и о процессорах: выполнение «тяжелых» задач, таких как высокопроизводительные вычисления, работа с большими СУБД и других, не поддающихся простому распараллеливанию, требует большой мощности от каждого ядра. Однако значительная часть серверной нагрузки (в особенности нагрузки, так или иначе связанной с Internet) складывается из выполнения большого количества мелких задач; вот для их решения гораздо лучше подходят многоядерные многопотоковые процессоры. Для такого рода задач величина получаемой ими мощности процессора не является слишком критичной; если перейти на более медленное ядро, то время выполнения задачи — скажем, обращения к Web-сайту, — может увеличиться, но оно в любом случае несопоставимо со временем человеческой реакции. Поэтому задержка, вызванная относительно невысокой величиной индивидуальной мощности одного потока в одном ядре, останется незаметной, зато суммарная высокая производительность сервера имеет большое значение — именно она определяет качество обслуживания.
В нынешних условиях реализовать преимущества многоядерных многопотоковых серверов можно на определенной, органичной для них нагрузке, поэтому о таких компьютерах конкуренты охотно говорят как о нишевых продуктах. Такие рассуждения верны, но только на текущий момент, в рамках унаследованной парадигмы программирования. Для того чтобы можно было воспользоваться преимуществами CMP в приложении к более широкому кругу задач, необходимо научиться преобразовывать длинные исполняемые последовательности команд в более короткие цепочки, чтобы их можно было выполнять параллельно. Пока такие методики существуют в языке Фортран применительно к работе с матричными операциями.
Революционер из МТИ
Наиболее радикален в выражении своего отношения к многоядерности и тем особенно интересен профессор Массачусетского технологического института Ананд Агарвал. Это, безусловно, один из крупнейших современных специалистов по процессорным архитектурам; в свое время он участвовал в разработке первой спецификации SPARC. Несмотря на солидный возраст, он по-юношески экстремален и выражает крайние взгляды, но при этом обнажает и наиболее полным образом выражает саму идею перехода от монолитных процессоров к многоядерным. К тому же созданная им компания Tilera показательна в качестве представителя нового поколения процессорных компаний, не имеющих собственного производства, но обладающих свежими мыслями и ресурсами для проектирования. Далеко не случайно именно Агарвал выступал в качестве одного из основных докладчиков на проводившихся в 2006 и 2007 году конференциях Multicore Expo. Он считает, что многоядерные системы станут столь мощной силой, что разрушат сложившуюся стабильную обстановку и заставят проектировщиков переосмыслить фундаментальные начала. Агарвал предлагает еще одну дополнительную формулировку для закона Мура, в соответствии с ней с периодом 18 или 24 месяца удваиваться должно не только число транзисторов, как это звучит в оригинале, но еще и число ядер на кристалле. Из этого следует, что при сегодняшних одном–восьми ядрах в начале следующего десятилетия их число превысит 1000.
Для того чтобы синхронизировать рост числа ядер в соответствии с ростом числа транзисторов (число транзисторов, приходящихся на ядро, по мнению профессора, возрастать не будет), необходимо сохранять простоту ядер, сокращая размеры кэш-памяти, и отказаться от других усовершенствований (суперскалярность, внеочередное исполнение и др.). Можно представить это так, что ядро возвращается к чистой архитектуре фон Неймана, а система на кристалле вбирает в себя всю инфраструктурную сложность. Агарвал предложил правило, названное (им KILL аббревиатура от kill if less than linear, то есть «убей, если меньше, чем линейно»). Правило это можно интерпретировать следующим образом: некоторый ресурс ядра может наращиваться, если при этом обеспечивается, как минимум, линейный рост производительности. Таким образом, утверждает Агарвал, можно найти оптимум для разного рода устройств, например кэш-памяти. Если уменьшить тактовую частоту с 4 до 1 ГГц, то вероятность промаха при обращении в стек уменьшается в четыре раза, и стек можно сделать в 16 раз меньше.
После того как выбрана архитектура ядра, следует решить второй вопрос — как объединить между собой ядра. Агарвал считает, что классическая шинная архитектура обречена, ей на смену придет решетчатая инфраструктура (mesh networking). Преимущество решетчатой (рис. 2), или ячеистой, сети состоит в том, что она обладает качеством самолечения, продолжая работать в случае выхода из строя узла или межсоединения. По Агарвалу решетчатая многоядерная архитектура будет распределенной, в ней не будет централизованных ресурсов.
Большая часть соображений профессора Агарвала реализуется в проекте RAW, который ведется под его руководством одной из исследовательских лабораторий Массачусетского технологического института.
Неизбежность расплаты
О параллелизме как о светлом будущем компьютерных систем ученые упорно говорили на протяжении всех последних 30-35 лет. Однако до тех пор, пока преодоление связанных с этим сложностей, например с необходимостью разделения приложений на потоки, компенсировалось непрерывно возрастающей производительностью процессоров, никто из производителей по понятным причинам инвестировать в эту перспективу не хотел. Поэтому до появления многоядерных процессоров параллельные вычисления оставались атрибутом суперкомпьютеров. Многолетнее игнорирование очевидного привело к тому, что, когда час пробил, оказалось, увы, к светлому будущему индустрия не готова, хотя, конечно же, есть отдельные острова готовности, не более того.
В роли мальчика, который открыл окружающим глаза на своеобразие королевского одеяния, выступил один из ведущих экспертов по современным языкам программирования, сотрудник корпорации Microsoft Херб Саттер.
Настоящим «бестселлером» оказалась простая по форме, но эпохальная по содержанию статья «Бесплатных завтраков не будет. Основополагающий разворот по направлению к параллельности в программировании» (The Free Lunch Is Over A Fundamental Turn Toward Concurrency in Software). Она была опубликована весной 2005 года сразу в двух журналах — Dr. Dobb’s Journal и C/C++ Users Journal. Суть статьи заключается в утверждении, что рост производительности процессоров, опережающий потребности, создал парниковые условия для программирования, что оказалось в конечном итоге не на пользу делу, как известно, эволюция в излишне благоприятной среде если не ведет к вырождению, то уж точно не формирует жизнестойкость, способность противостоять перегрузкам. Существовавшие до сих пор условия Саттер сравнил с бесплатной раздачей завтраков, которая закончилась. Немного позже Саттер вместе с коллегой из Microsoft Джеймсом Ларуссом опубликовал статью «Программное обеспечение и параллельная революция» (Software and the Concurrency Revolution), на этот раз в журнале ACM Queue, где он не столько критиковал настоящее, сколько размышлял о будущем. В ней Саттер назвал необходимую реакцию на изменившиеся условия «грядущей параллельной революцией».
Саттер уверен: многоядерные машины — наше неизбежное будущее, а потому главная задача заключается в необходимости научиться программировать для них. Новые компьютеры будут все более и более производительными, но программирование не сможет далее развиваться за счет умения «оседлать волну производительности». Основное направление развития — параллелизм. Сейчас об этом говорят очень многие, но Саттер был одним из первых, кто сделал это публично и в очень яркой форме. Ниже приведено изложение его «манифеста».
Нынешнее состояние дел в области языков программирования и сопутствующих технологий он сравнивает примерно с тем, что было в начале переходного периода к структурному программированию. На уровне ассемблера сегодня существуют инструменты семафоров и копрограмм (coroutine), на более высоком структурном уровне — блокировки и потоки. Требуемые механизмы можно сравнить с произошедшим в свое время переходом к объектно-ориентрованным технологиям: нужен более высокий уровень абстракции, на котором можно было бы строить параллельные программы, подобно тому как объектно-ориентированные подходы позволяют строить сложные компонентные программы.
Есть основания полагать, что последствия параллельной революции окажутся значительнее, чем объектно-ориентированной, потому что за ней стоит не просто повышение производительности труда программистов, а повышение системной производительности в целом. Появление объектно-ориентированных языков оставило место языкам программирования прежних поколений, тому же Си, например. Если параллельность станет главным инструментом и основным путем повышения производительности, то она не оставит места тем языкам, которые не смогут ее поддерживать. Они смогут сохраниться только в тех приложениях, в которых производительность и использование современного аппаратного обеспечения не имеют значения.
Изменения в клиентских программах будут существенно больше, чем в типичных серверных приложениях. Обычная серверная вычислительная нагрузка, особенно Web-приложения, по своей внутренней природе достаточно распараллелена, кроме того, в данном случае проблемы уже частично решены средствами операционных систем, которые давно поддерживают разного рода многопроцессорные конфигурации и в которых накоплен значительный опыт решения проблем, связанных с необходимостью масштабирования.
Мир клиентских приложений не столь структурирован и регулярен. Обычно они представляют собой один процесс, выполняемый от имени одного пользователя, поэтому для распараллеливания приложения придется делить на более мелкие части. Сложность усугубляется тем, что фрагменты эти должны каким-то образом взаимодействовать между собой и использовать общие массивы данных. Схожие проблемы возникают и на серверах в тех случаях, когда они используются для высокопроизводительных вычислений и для работы с большими базами и хранилищами данных.
Для распараллеливания может быть использовано несколько программных моделей, каждая из которых соответствует определенному подмножеству требований. Заранее может быть сложно определить, какая именно модель лучше подходит, еще больше сложностей возникает в связи с потребностью комбинировать различные модели. Но несмотря на все многообразие, пространство решений можно описать системой координат, где по одной оси откладывается уровень гранулярности, а по другой — степень взаимосвязанности между параллельными модулями.
Вообще говоря, гранулярность может варьироваться от одной или нескольких команд до таких фрагментов, выполнение которых занимает часы или даже дни. Понятно, что чем меньше размер фрагмента, тем больше удельные затраты на обеспечение параллельности. Преимущество нынешних и будущих многоядерных процессоров по сравнению с обычными многопроцессорными системами состоит в том, что существенная часть работы, связанная с коммуникациями и синхронизацией, решается на аппаратном уровне, поэтому на программное обеспечение выпадает необходимость распараллеливания не на самом нижнем уровне грануляции (это в некотором смысле достаточное условие для распараллеливания приложений).
Вторая ось — связанность по данным. в идеале было бы замечательно, если бы каждый фрагмент работал со своим собственным автономным фрагментом данных, в таком случае все сводится к оптимальной загрузке ядер потоками команд и исключено явление, называемое «гонкой данных» (data race), но в реальной жизни независимость по данным встречается не часто. Можно выделить три типа параллелизма.
-
Независимый параллелизм (Independent parallelism). В этом случае одна или несколько операций прилагаются независимо друг от друга к одному и тому же фрагменту данных. По степени гранулярности задачи с независимым параллелизмом могут распределяться от простейших действий над массивами данных до поисковых машин или систем моделирования методом конечного элемента в строительной механике и им подобных.
-
Регулярный параллелизм (Regular parallelism). Этот вид параллелизма относится к регулярным структурам, он предполагает, что между изменениями фрагментов данных есть логическая, или функциональная, зависимость.
-
Неструктурированный параллелизм (Unstructured parallelism). Не предполагает какой-либо взаимозависимости между отдельными фрагментами данных. Последний тип данных является наиболее общим; для работы с ними обычно использовались различного рода технологии с блокировками.
Основная проблема, сопровождающая блокировки, заключается в том, что не существует точных указаний, как их следует делать, все определяется избранной программистом дисциплиной, он должен помнить о существовании соответствующих блокировок при обращении к тем или иным данным. Кроме того, блокировки плохо поддаются локализации, поэтому все, кто обращаются к данным, должны помнить о них и учитывать факт их существования.
На данный момент по отношению к блокировкам существует два основных альтернативных подхода. Первый подход называют «программированием, свободным от блокировок». В основе этого подхода лежит глубокое понимание модели памяти, реализованной в процессоре, оно позволяет создавать такие структуры данных, которые обеспечивают распределенное использование данных без блокировок. Недостатком этого подхода является его трудоемкость и невысокая надежность.
Второй подход получил название «программная транзакционная память» (Software Transactional Memory, STM). В его основе лежит механизм обмена транзакциями, аналогичный тому, который используется в базах данных. В конце 80-х годов возникла идея переноса принципов STM на аппаратное обеспечение, но практические результаты получены только в последние годы. Есть основания полагать, что процессоры наподобие Rock будут комплектоваться памятью с железной реализацией транзакционного механизма.
Свою статью Саттер заключает тем, что показывает несоответствие требованиям параллелизма популярных императивных коммерческих языков (Паскаль, Си, C++, Java, C#), более новых функциональных языков (Scheme, ML, Haskell), иных инструментальных средств. В этой области есть определенные академические наработки, однако потребуется время на то, чтобы они были доведены до уровня коммерческих продуктов.
Многоядерное будущее
Эволюция технологий связана с количественными и качественными переходами. Парусники заменили пароходы, поршневые двигатели самолетов уступили место турбинам и т.д. Каждый такой переход сопровождается созданием новых инженерных и научных школ. Нечто подобное являют собой многоядерные процессоры. Черты этой революционной парадигмы пока еще только вырисовываются.
Идея перехода на многоядерные процессоры стала овладевать умами масс специалистов в области ИТ совсем недавно, примерно начиная с 2005 года, но на самом деле она далеко не так нова. Еще в далекие 60-е годы преимущества нескольких процессорных ядер перед одним обосновал Сеймур Крей, затем он реализовал свой замысел в суперкомпьютере CDC 6600. Но в силу консервативности взглядов проектировщиков, вызванных технологическими ограничениями (например, компьютерные платы собирались навесным монтажом из триодов, конденсаторов, сопротивлений и прочих дискретных компонентов), дальнейшего развития этот подход к проектированию центрального процессорного пстройства не получил.
За возрождение многоядерности на современном технологическом уровне, как и за многие другие новации, мы должны быть благодарны инженерам корпорации Digital Equipment. Именно здесь во второй половине 90-х всерьез, на промышленном уровне, задумались о многоядерности в микропроцессорах; это произошло при переходе процессора от Alpha 21164 (EV5) к Alpha 21264 (EV6). Тогда исследователям из DEC удалось установить две важные закономерности, распространяющиеся на процессоры. Во-первых, оказалось, что для линейного роста производительности монолитных (одноядерных) процессоров требуется обеспечить квадратичный рост числа транзисторов. Во-вторых, как следствие, также нелинейно (хотя и трудно сказать, как именно) возрастет сложность проектирования. Элементарное рассуждение подсказывает, что суммирование производительности нескольких ядер даст ту же совокупную производительность, что и одно ядро при меньшем числе транзисторов. Вопрос в том, как объединить мощности отдельных ядер, в этом состоит коренная проблема многоядерности. Реакцией DEC на обнаруженные проблемы стал проект Piranha, предполагавший создание 8-ядерного процессора, где каждое ядро должно было иметь отдельную кэш-память для команд и данных, для совместной работы процессоры объединялись коммутатором. Однако после перехода в ведение Compaq проект Piranha был похоронен, процессор так и не был реализован.
Низкая эффективность использования транзисторов, когда большая их часть отдается схемам управления и существенно меньшая — выполнению собственно арифметических и логических операций, и, как следствие, высокое энергопотребление, стали главным тормозом на пути дальнейшего развития монолитных процессоров. Весьма наглядной иллюстрацией происходящего стало явление, получившее название «разрыв Мура» (The Moore’s gap). Сложность проектирования увеличивает время проектирования некоторых наиболее сложных процессоров до неприемлемых значений; в некоторых случаях период проектирования затягивается больше чем на десятилетие. Характерный пример — прогноз выпуска серверов архитектуры IA-64. На пороге третьего тысячелетия перспектива серверного микропроцессора казалась многим очевидной; будущая монополия Itanium (тогда проект еще назывался Merced) не вызывала сомнения, открытым оставался лишь вопрос о времени ее появления. Практические же результаты оказались столь скромными, что дали основания скептикам с издевкой называть процессор не иначе как Itanic. Рынок серверов инерционнее рынка рабочих станций, поэтому, чтобы увидеть будущее, стоит смотреть на изменения, происходящие во втором сегменте. Примерно три-четыре года назад исчезли рабочие станции на Itanium, это явный знак судьбы этого процессора.
Параллельно с проектом Piranha группа исследователей из Стэндфордского университета во главе с Кунле Олокотуном работала над «многоголовым процессором» Hydra, весьма образно названным именем чудовища, с которым сражался Геракл. В качестве ядра использовался процессор MIPFS 4600. Работа (заметим, спонсировавшаяся агентством DARPA) дала хорошие результаты. Как обычно бывает в таких случаях, проект перевели на коммерческую основу, создали небольшую фирму Afara, которую возглавил тот же Олокотун. Впоследствии, проявив изрядную прозорливость, причем в далеко не самые простые для себя времена, Sun Mirosystems купила эту компанию и, заменив ядро MIPFS 4600 на UltraSPARC II и увеличив число ядер вдвое, выпустила экспериментальный процессор Niagara, получивший в серии наименование UltraSPARC T1.
Успеху Niagara способствовало и то, что в Sun велась собственная разработка двухъядерного процессора MAJC 5200, где каждое ядро способно обрабатывать четыре потока команд. Процессор UltraSPARC T1 является конвергенцией Hydra и MAJC 5200.
Процессоры SPARC вообще и UltraSPARC T1 в частности являются суперскалярными, а в Power от IBM еще используется метод внеочередного исполнения. Первым процессором с двумя ядрами стал Power4 (два ядра Power3), за ним последовал Power5, а на горизонте тоже двухъядерный Power6. Может показаться странным, но у IBM разработки многоядерных процессоров заметно связаны с производством игр. Так, процессор Xenon предназначен для игровой консоли, которая, как предполагается, придет на смену Xbox 360, он будет иметь три ядра PowerPC, где каждое ядро будет поддерживать два симметричных аппаратных потока. Другой проект, Cell, включает двухпотоковое ядро SMT Power и восемь ядер, которые называют синергетическими процессорными элементами (Synergistic Processing Element, SPE), работающими по принципу SIMD. Основное ядро Power выполняет команды из системы команд PowerPC, поддерживая специализированную систему команд SPE. С очевидным опозданием свои предложения сделали корпорации AMD и Intel: борьба на многоядерном поле стала и для производителей процессоров архитектуры x86 одним из самых актуальных вопросов сегодняшнего дня.
Отдельную нишу в «многоядерном пространстве» занимают компании, производящие процессоры для коммуникационных устройств, в том числе Broadcom SiByte, Raza Microelectronics, Cavium Networks, Octeon.
Через несколько лет многоядерные процессоры станут обыденностью: проблемы конструирования и поддержки средствами полупроводниковых технологий решаются достаточно просто, в этом собственно и состоит одно из достоинств. Компании, производящие процессоры, это прекрасно понимают, но они также понимают, что гораздо сложнее другое — адаптировать их для работы с существующими приложениями. Поэтому выбор момента и методов перехода на новые рельсы так сложен и ответствен. Если выстрелить слишком рано, можно опередить рынок, но, с другой стороны, слишком позднее решение может обернуться большим ущербом.