Портал создан при поддержке Федерального агентства по печати и массовым коммуникациям.

ЭЛЕКТРОННЫЙ ЮЛИЙ ЦЕЗАРЬ

Д. УСЕНКОВ.

До недавнего времени тема так называемого параллельного программирования считалась узкоспециальной и её обсуждало лишь небольшое число программистов, разрабатывающих операционные системы для крупных серверов или программное обеспечение суперкомпьютеров. Сегодня, когда получили широкое распространение многоядерные процессоры, основные принципы параллелизации вычислений полезно знать обычным пользователям современных персональных компьютеров.

Компьютеры-многостаночники

На заре компьютерной эры первые ЭВМ стоили очень дорого и их простой хотя бы на секунду считался недопустимым. Человек же, работая с машиной, не успевал за её быстродействием (по нынешним меркам совсем невысоким): например, при вводе данных с клавиатуры или печати тратится значительное время, а процессор пока вынужден был «бездельничать».

Чтобы ЭВМ не простаивала и её машинное время использовалось максимально полно, процессор был устроен так, что обслуживал сразу несколько пользователей, сидящих каждый за своим терминалом (дисплей и клавиатура). И если кто-то из них отвлекался, например, на чтение с экрана результатов своих расчётов или ждал их распечатки, то процессор продолжал действовать, обрабатывая информацию с других терминалов.

Поэтому родилось понятие многозадачность: компьютер, решая поставленные вычислительные задачи (запущенные программы), должен был действовать так, чтобы пользователям казалось, что их программы выполняются параллельно, то есть одновременно и независимо друг от друга.

Постепенно стоимость компьютеров и их размеры снизились, а быстродействие выросло. Они стали занимать небольшое пространство на письменном столе, и у них появился персональный хозяин. Главной ценностью стало считаться рабочее время человека — оператора, программиста, пользователя, даже если часть этого времени процессор компьютера простаивал. Казалось бы, необходимость в одновременном выполнении нескольких программ исчезла: ведь пользователь, как правило, работает только с одной программой зараз. Однако на самом деле это далеко не всегда так: ведь существует целый ряд задач, которые компьютер должен решать в течение всего времени работы, в том числе автоматически, независимо — и даже скрыто — от пользователя. Это могут быть антивирусный контроль, отслеживание поступления свежей электронной почты и другие фоновые программы.

Да и некоторые современные прикладные программы могут требовать выполнения нескольких действий: например, проигрыватель цифрового видео должен одновременно считывать данные с DVD-диска, распаковывать их из формата, в котором они записаны ради уменьшения объёма, и выводить изображение и звук на экран. Наконец, самому пользователю может понадобиться запустить сразу несколько программ (приложений) одновременно, чтобы, переключаясь между ними, выполнять какие-то действия то в одной, то в другой из них.

Так что современный компьютер, подобно Юлию Цезарю, практически всегда выполняет одновременно сразу несколько дел. Как же это ему удаётся?

Компьютерный пинг-понг, или многозадачность «понарошку»

Недавно существовал достаточно простой способ «одновременного» выполнения нескольких программ: операционная система обеспечивала независимость программ одной от другой, выделяя каждой из них отдельную область памяти или даже имитируя (эмулируя) как бы отдельный виртуальный компьютер и распределяя вычислительную мощность процессора между всеми программами. Для каждой из них система выполняла по очереди некоторую небольшую порцию команд. Для сравнения представьте магазин, где работает одна касса, к которой стоят сразу, скажем, три очереди. Кассирша обслуживает одного человека из первой очереди, потом из второй, из третьей, затем — снова из первой и т.д.

Если такие порции команд, поочерёдно выполняемые для каждой программы, будут достаточно малы, то для пользователя переключение процессора с одной программы на другую окажется незаметным — так же, как мы не замечаем, например, смену отдельных кадров в кинофильме. Пользователю будет казаться, что все программы действительно выполняются одновременно.

Здесь возможны два варианта. Если все открытые программы равноправны, то для каждой на элементарном шаге выполняется одинаковое число команд, а значит, скорость их работы будет примерно одинаковой, причём чем больше этих программ запущено, тем медленнее работает каждая из них. Но если какая-то программа особенно важна, то можно назначить ей более высокий приоритет, и тогда для этой программы на каждом элементарном шаге будет выполняться больше команд, чем для остальных, а значит, относительная скорость её работы возрастёт.

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

Змеи Горынычи компьютерного мира

Возвращаясь к примеру с обслуживанием очереди в магазине, невольно задаёшься вопросом: а не проще ли поставить не один, а несколько кассовых аппаратов?

К похожему выводу относительно проблемы многозадачности пришли в своё время и разработчики ЭВМ, сконструировав многопроцессорные системы — компьютеры, в схеме которых предусмотрено два процессора или более.

Другой возможный вариант — кластерные системы (от англ. claster — скопление, куча), когда, по сути, в единый вычислительный комплекс объединено несколько (иногда несколько десятков) обычных однопроцессорных компьютеров. Получается вроде Змея Горыныча — сказочного существа о многих головах.

Такие унифицированные и взаимозаменяемые модули, из которых, как из кубиков детского конструктора, можно собрать, например, мощный сервер, называют «лезвиями». Название объясняется, возможно, тем, что их ровные ряды, установленные в каркасе, напоминают лезвия в бритвенном станке.

Конечно, многопроцессорный компьютер — а тем более кластер — стоит намного дороже, чем обычный однопроцессорный ноутбук. Но ведь и задачи с их помощью решают очень сложные: кластерные ЭВМ используют в основном в качестве суперкомпьютеров (см. «Наука и жизнь № 12, 2004 г.) или мощных серверов. «Многоголовость» позволяет поручить каждому процессору выполнение какой-то отдельной программы, а если речь идёт, например, об интернет-сервере, то каждый процессор может обслуживать один из сеансов обращения к данному серверу кого-либо из посетителей сайта.

Параллельное программирование

Впрочем, принцип «каждому процессору — свою программу» — это самый примитивный вариант решения многих задач одновременно. Наличие в компьютере нескольких вычислительных узлов позволяет реализовать параллельное программирование — особый принцип работы, значительно увеличивающий его быстродействие.

Пусть, например, надо вычислить сумму 100 чисел, а быстродействие процессора таково, что на каждое сложение затрачивается одна секунда. Очевидно, что если мы (как это и делается в большинстве стандартных алгоритмов вычисления суммы) зарезервируем под хранение результата переменную и будем в цикле прибавлять к ней одно число за другим, то на все вычисления (если не считать дополнительных затрат машинного времени на организацию собственно цикла) нам потребуется 100 с.

А теперь пусть в нашем распоряжении не один, а четыре процессора. Тогда можно заставить каждый из них одновременно рассчитать промежуточные суммы по 25 чисел, а затем сложить уже эти суммы.

Как видим, даже в этом простейшем случае мы получим искомую сумму всего за 27 с, то есть выиграем в быстродействии почти вчетверо.

Аналогичным способом можно запараллелить и многие другие вычислительные операции. Например, можно разделить обрабатываемое растровое изображение (скажем, при автоматической оптимизации его цветовой гаммы) на несколько фрагментов и поручить каждому процессору собственный «фронт работ». Очевидно, что такое разделение программы на несколько одновременно (параллельно) выполняемых фрагментов, или вычислительных потоков, ускоряет получение результата.

Другой гранью параллелизации вычислений становится повышение экономичности компьютера. В последние годы происходила настоящая «гонка» за тактовой частотой. Процессоры, словно сердце спринтера, «застучали» быстрее — с десятков килогерц до нескольких гигагерц, сокращая время, затрачиваемое на выполнение одной команды программы. Однако позже выяснилось, что этот путь ведёт в тупик: рано или поздно будет достигнут технологический предел роста тактовой частоты. Но уже сейчас, когда до предела ещё далеко, у конструкторов процессоров возникают серьёзные проблемы, поскольку даже при небольшом увеличении тактовой частоты заметно возрастает выделение тепла, которое нужно эффективно отводить от процессора. В последние два-три года пошла речь не только о жидкостных, но даже о криогенных системах охлаждения для наиболее мощных и быстрых компьютеров! Ведь увеличение тактовой частоты на 20%, которое даёт прирост быстродействия 13%, повышает рост энергопотребления на 73%. Уменьшение тактовой частоты на те же 20%, снижая быстродействие на 13%, уменьшает расходы энергии на целых 49%.

Применив принципы параллельного программирования и установив в компьютере два процессора со сниженной на 20% тактовой частотой, можно получить суммарное быстродействие в 1,7 раза больше, а расход энергии при этом возрастёт всего лишь на 2%!

Таким образом, именно параллельное программирование позволяет «интенсифицировать» вычисления, наращивать быстродействие, почти не увеличивая тепловыделения. Осталось лишь сделать многопроцессорные системы дешевле. И это уже свершилось!

Два процессора в одном

О технологии Hyper-Threading широко заговорили после 14 ноября 2002 года, когда фирма «Intel» представила новый процессор Pentium 4 с тактовой частотой 3,06 ГГц, предназначенный для офисных рабочих станций и домашних компьютеров. Несколько позже аналогичную технологию применила фирма AMD, извечный конкурент «Intel».

Не вдаваясь в глубокие технические подробности, можно сказать, что установленный в персональном компьютере один физический процессор воспринимается операционной системой как два отдельных процессора, одинаковые по своим характеристикам. И, как в описанных выше многопроцессорных системах, можно поручить каждому из этих «виртуальных» процессоров свою отдельную программу либо применить алгоритм параллелизации вычислений.

И всё же с помощью новой технологии нельзя добиться всего, что доступно многопроцессорным системам. Она лишь позволяет более рационально использовать ресурсы процессора и распределять его машинное время между несколькими программами. Дело в том, что современный процессор содержит в себе несколько арифметико-логических узлов, которые специализированы на выполнении тех или иных вычислительных операций, например для вычислений с плавающей запятой или для обработки мультимедийных данных. Но в реальных условиях специальные команды встречаются не всегда, так что если какой-то из таких узлов своего «спецзадания» не получил, то он может использоваться по другому назначению.

Когда каждый из двух «виртуальных процессоров» выполняет «свою» программу, то при приостановке одной из них, например в ожидании ввода данных или распечатки очередной порции информации на принтере, можно отдать больший процент вычислительной мощности реального физического процессора активному в данный момент «виртуальному» процессору.

Реализация параллельных вычислений на аппаратном уровне (ведь с точки зрения операционной системы она имеет дело с двумя отдельными полноценными процессорами) позволяет сделать это более надёжно, чем псевдомногозадачность при постоянных переключениях процессора с одной программы на другую.

В итоге удаётся получить выигрыш в быстродействии в 30–40% практически без роста энергопотребления. А стоимость компьютера с таким процессором значительно ниже, чем многопроцессорной системы.

Эпоха многоядерных процессоров

Впрочем, технология Hyper-Threading оказалась лишь экспериментом. Весной 2006 года появились двухъядерные процессоры Intel Core 2 Duo, а вскоре и аналогичные им AMD Athlon 64х2 и Turion 64х2 (см. «Наука и жизнь № 7, 2006 г.).

Создание двухъядерных (и вообще многоядерных) процессоров стало возможным благодаря совершенствованию технологий микроэлектроники: размеры транзисторов, формируемых на кристалле микропроцессора, становятся всё меньше, а значит, на той же площади можно разместить больше элементов.

Двухъядерный процессор фактически содержит на одном кристалле два отдельных одинаковых микропроцессора, имеющих общую кэш-память и общую шину ввода-вывода команд программы и данных. Компьютер с таким процессором стоит чуть дороже, но обладает всеми преимуществами двухпроцессорного: заметным приростом быстродействия при сравнительно невысокой тактовой частоте и очень незначительном росте энергопотребления.

Сейчас, спустя всего полтора года после появления первого двухъядерного процессора, одноядерные процессоры для настольных компьютеров, ноутбуков и серверов практически уже не выпускают. Появились и четырёхъядерные модели, например Core 2 Quad, а в ближайших планах выпуск процессоров с числом ядер 8 и больше. В проекте выпуск 16-ядерного процессора, в котором часть ядер станет выполнять специальные функции, например по работе с локальной сетью или с высокореалистичной графикой, а все ядра будут связаны между собой сетью каналов передачи данных, что позволит значительно ускорить работу компьютера по сравнению с ныне используемыми сетевыми платами или внешними видеоконтроллерами.

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


Случайная статья


Другие статьи из рубрики «Человек и компьютер»