Массив процессорных элементов
Рис. 10.1. Матричный процессор Массив процессорных элементов может использоваться для обработки двухмерных данных. Например, если каждый элемент массива определяет точку в пространстве, то массив может служить для вычисления значений температуры внутри плоской теплопроводной поверхности. Предположим, что температура на ее краях постоянна. Приближенное решение в дискретных точках, представленных процессорными элементами, формируется так. В начальный момент времени процессорные элементы, расположенные на границе области, инициализируются некоторыми заданными значениями температуры, а все внутренние точки — произвольными, не обязательно одинаковыми, значениями. Затем все элементы начинают параллельно оценивать значения температуры в соответствующих точках как среднее арифметическое значений температуры в четырех соседних точках. Вычисления повторяются до тех пор, пока разность результатов последовательных вычислений не окажется меньше некоторого указанного значения. Для выполнения таких расчетов необходимо, чтобы каждый элемент матричного процессора обеспечивал обмен данными с соседними элементами через показанные на рисунке соединения. Каждый элемент должен иметь несколько регистров и небольшой объем локальной памяти для хранения данных. Кроме того, важно наличие у элемента так называемого сетевого регистра, служащего для обмена данными с соседними элементами. Центральный процессор направляет всем элементам команду пересылки значений сетевых регистров на один уровень вверх, вниз, вправо или влево. Каждый элемент должен содержать АЛУ для выполнения арифметических команд, получаемых от центрального процессора. Организовав итеративный цикл, с помощью этих базовых средств команды элементам можно передавать многократно. При этом необходимо, чтобы управляющий процессор определял момент, когда каждый процессорный элемент вычислит температуру в определенной точке с указанной точностью. С этой целью по достижении заданного значения внутренний бит состояния каждого из элементов должен устанавливаться в 1. Соединения между элементами позволяют контроллеру устанавливать все биты состояния в 1, что равнозначно завершению операции.
При разработке матричных процессоров возникает вопрос: что эффективнее использовать — несколько мощных процессоров или большое количество очень простых процессоров. Примером реализации первого подхода может служить суперкомпьютер ILLIAC-IV. В его состав входят 64 процессора, обрабатывающих 46-разрядные числа. Примером реализации второго подхода является применение матричных процессоров, разработанных в конце 1980-х годов. В системе СМ-2 производства корпорации Thinking Machines можно было установить до 65536 процессоров, но разрядность каждого из них равнялась одному биту. В системе Maspar MP-1216 допускалась установка 16384 процессоров разрядностью 4. Системы Cambridge Parallel Processing Gamma II Plus могли содержать до 4096 процессоров, обрабатывающих данные длиной в 1 байт или 1 бит. Разработчики этих систем полагали, что в SIMD-архитектуре наличие высокого уровня параллелизма эффективнее использования небольшого количества мощных процессоров. Сфера применения матричных процессоров является достаточно узкой. В первую очередь они предназначены для решения вычислительных задач, связанных с обработкой матриц и векторов. Напомним, что для решения подобных задач подходят и суперкомпьютеры с векторной архитектурой. Главным отличием матричных процессоров от векторных систем является то, что при работе со вторыми высокая производительность достигается за счет интенсивной конвейеризации, а при использовании первых — за счет максимальной степени параллелизма, являющегося результатом параллельной работы компьютерных модулей. Но ни матричные, ни векторные компьютеры не могут значительно ускорить обычные вычисления, поэтому они не пользуются коммерческим успехом.
10.3. Архитектура мультипроцессорных систем общего назначения Описанные в предыдущем разделе матричные системы предназначены для выполнения вычислений с ярко выраженным параллелизмом данных. Для других задач, где нет столь явно выраженного параллелизма данных, гораздо лучше подходит архитектура MIMD, в которой множество процессоров могут независимо и параллельно выполнять разные подпрограммы. На рис. 10.2, 10.3 и 10.4 продемонстрированы три возможных способа реализации мультипроцессорной системы типа MIMD. Самая простая система представлена на рис. 10.2. Она состоит из n процессоров, k модулей памяти и коммуникационной сети, связывающей процессоры и память. Сеть может стать причиной значительной задержки при обращении процессора к памяти. Система, в которой такая задержка одинакова для всех операций доступа к памяти, называется мультипроцессорной системой с однородным доступом к общей памяти (Uniform Memory Access, UMA) или системой с общей памятью. Поскольку процессоры выполняют команды с огромной скоростью, слишком большие задержки на выборку из памяти команд и данных для них не приемлемы. Однако коммуникационные сети с малым временем задержки имеют очень сложную структуру и высокую стоимость. Модули памяти Рис. 10.2. Мультипроцессорная система типа UMA Достичь высокого быстродействия всех процессоров можно путем непосредственного соединения с ними модулей памяти. Архитектура такой системы показана на рис. 10.3. Каждый процессор имеет доступ не только к собственной локальной памяти, но и к памяти других процессоров сети. Но поскольку при обращении к памяти других процессоров запросы проходят через сеть, они выполняются дольше, чем обращения к локальной памяти. Системы этого типа называются мультипроцессорными системами с неоднородным доступом к памяти (Non-Uniform Memory Access, NUMA).
Рис. 10.3. Мультипроцессорная система типа NUMA В схемах, приведенных на рис. 10.2 и 10.3, используется глобальная память, к каждому из модулей которой может обратиться любой из процессоров. На рис. 10.4 демонстрируется схема иной организации системы, характеризующаяся тем, что все модули памяти являются собственностью непосредственно соединенных с ними процессоров. Ни один из процессоров не может обратиться к удаленной памяти без взаимодействия с удаленным процессором, которому она принадлежит. Взаимодействие между этими двумя процессорами осуществляется в форме обмена сообщениями. Системы такого типа называются системами с распределенной памятью и высокоскоростным протоколом передачи сообщений. Рис. 10.4. Мультипроцессорная система с распределенной памятью До сих пор в этом разделе в качестве основных функциональных устройств мультипроцессорной системы рассматривались процессоры и модули памяти. Мы не обсуждали модули ввода-вывода, хотя любая мультипроцессорная система обязательно должна иметь эффективные инструменты такого рода. Существуют разные средства, предназначенные для ввода и вывода информации. Отдельные модули ввода-вывода могут быть соединены прямо с коммуникационной сетью, обеспечивая стандартные интерфейсы ввода-вывода, о которых рассказывалось в главе 4. Кроме того, некоторые функции ввода-вывода могут быть интегрированы прямо в процессорные модули. Высокоуровневое представление возможных способов организации мультипроцессоров показано на рис. 10.2, 10.3 и 10.4. Производительность и стоимость подобных систем в значительной степени зависит от того, как реализованы их схемы. В следующих двух разделах речь пойдет о наиболее популярных схемах организации сетей обмена и о структуре иерархии памяти. 10.4. Коммуникационные сети А сейчас мы рассмотрим возможные способы реализации коммуникационных сетей в мультипроцессорных системах. Коммуникационная сеть должна обеспечивать передачу данных между любыми двумя модулями системы. Кроме того, сеть может использоваться для широковещательной передачи информации от одного модуля системы ко многим другим. Трафик в сети формируется из запросов (например, на чтение или запись), пересылаемых данных и различных команд.
Каждая конкретная сеть характеризуется такими параметрами, как стоимость, полоса пропускания, реальная скорость передачи данных и простота реализации. Термин полоса пропускания обозначает пропускную способность соединений и определяется как количество битов или байтов данных, которые могут проходить через это соединение за единицу времени. Реальная скорость передачи данных соответствует реальному объему данных, проходящему через соединение за единицу времени. Она меньше полосы пропускания, поскольку при передаче данных могут возникать паузы. Информация по сети передается, как правило, в виде пакетов фиксированной длины и фиксированного формата. Например, запрос на чтение может представлять собой один пакет, содержащий адрес источника (процессорного модуля) и места назначения (модуля памяти), а также поле команды, где указан тип операции чтения, которую требуется выполнить. Запрос на запись одного слова в модуль памяти тоже может состоять из одного пакета, содержащего записываемые данные. А вот ответ на запрос чтения, включающий целый блок кэш-памяти, может пересылаться в виде нескольких последовательных пакетов. Несколько пакетов может потребоваться и для длинных сообщений. В идеале полный пакет должен пересылаться между любыми двумя узлами сети за один такт в параллельном режиме. Для этого нужны соединения, состоящие из большого количества проводов. Однако в целях упрощения архитектуры и снижения стоимости сети соединения обычно делают более узкими, а пакеты разделяют на части, каждая из которых может быть переслана за один такт. Общая шина Простейший и самый экономичный способ объединения большого количества модулей в единую систему заключается в использовании общей шины. Эта архитектура обсуждалась в предыдущих разделах при обсуждении устройства компьютеров, все сказанное там применимо и к мультипроцессорным системам. Поскольку несколько модулей соединены с одной шиной и каждому из них в любой момент может быть направлен запрос на передачу данных, необходима эффективная арбитражная схема. Самым простым режимом функционирования системы с общей шиной является режим, при котором шина предоставляется конкретной паре компонентов на все время операции передачи данных. Например в случае, когда процессор выдает запрос на чтение, он занимает шину до тех пор, пока не получит из памяти нужные данные. Поскольку модулю памяти для доступа к данным требуется некоторое время, шина простаивает с момента получения запроса до тех пор, пока память не будет готова вернуть данные. Готовые данные направляются процессору, и когда процесс передачи завершается, шина может быть выделена для выполнения другого запроса.
Существует схема под названием протокол с разделением транзакций, позволяющая использовать время простоя шины для обработки другого запроса. Рассмотрим следующую процедуру обработки последовательности запросов на чтение, поступающих от разных процессоров. После передачи адреса, указанного в первом запросе, шина может быть переназначена для передачи адреса, заданного в другом запросе. В случае, если данный запрос адресован другому модулю памяти, с этого момента два модуля памяти могут обрабатывать полученные запросы параллельно. Если ни один из модулей еще не завершил операцию обращения к памяти, шина может быть выделена третьему запросу и т. д. Когда первый модуль наконец завершит цикл обращения к памяти, он воспользуется шиной для передачи слова запросившему его компоненту. Обратите внимание, что фактическое время между выдачей адреса и получением слова не является критически важным параметром. Операции передачи адреса и данных для различных запросов выполняются независимо и могут чередоваться друг с другом. Возможность более эффективного использования полосы пропускания шины обеспечивает протокол с разделением транзакций. Достигаемая с его помощью производительность зависит от соотношения времени доступа к памяти и времени передачи данных по шине. Производительность можно повысить за счет усложнения архитектуры шины. А необходимость в ее усложнении вызвана двумя причинами. Во-первых, поскольку модулю памяти нужно знать, от какого источника поступил данный запрос, к запросу должен присоединяться тег идентификации источника. После выполнения запроса этот тег используется для отправки источнику требуемых данных. А во-вторых, не только процессор, но и все остальные модули должны иметь возможность выступать в роли хозяев шины. Мультипроцессорные системы, в которых применяется шина с разделением транзакций, содержат от 4 до 32 процессоров. Возможность подключения еще большего количества процессоров ограничена полосой пропускания шины. Для увеличения полосы пропускания можно увеличить количество составляющих шину линий. Сети с координатной коммутацией На рис. 10.5 показана сеть с коммутируемыми соединениями. Эта схема, разработанная для телефонных сетей, называется координатным коммутатором (crossbar switch). Для наглядности все ключи на рисунке изображены в виде механических выключателей, но на самом деле это, конечно же, электронные ключи. В приведенной схеме любой модуль, Q i,может быть соединен с другим модулем, Q j путем замыкания соответствующего ключа. Сети, в которых существует прямое соединение между любой парой узлов, именуются полносвязными. В полносвязной сети может выполняться множество параллельных операций передачи. Если n узлов должны переслать данные n другим узлам, все эти операции могут быть выполнены одновременно. Сеть, в которой операции передачи никогда не блокируются из-за отсутствия свободного пути, называется сетью без блокировок. На рис. 10.5 в каждой точке пересечения соединений показан единственный ключ. Однако в реальном мультипроцессоре используются более сложные соединения, и поэтому в каждой точке располагается целый набор ключей. В сети, соединяющей n модулей, число точек пересечения равняется n2, поэтому с увеличением количества модулей возрастает и общее число ключей. В результате сеть получается громоздкой и дорогостоящей. По этой причине координатная коммутация обычно применяется для сетей с небольшим количеством узлов.
Рис. 10.5. Сеть с координатной коммутацией Многоступенчатые сети В описанных выше системах с общей шиной и координатной коммутацией используется одноступенчатое соединение между любыми двумя модулями. Можно создать такую сеть обмена, в которой соединение между двумя узлами будет формироваться с помощью нескольких ступеней ключей. На рис. 10.6 показана трехступенчатая сеть, соединяющая восемь модулей. Из-за особенностей структуры соединений ее элементов эта сеть получила название коммутационной сети с перетасовкой (shuffle) — по аналогии с перетасовкой игральных карт путем разделения колоды карт на две части и последующего их объединения с чередованием карт из обеих частей. Каждый прямоугольник на рис. 10.6 представляет собой переключатель 2х2, который может соединить любой из входов с любым из выходов. Кроме того, если оба входа должны быть соединены с разными выходами, он может соединить их как прямо, так и накрест. Если два входа запросили один и тот же выход, может быть удовлетворен только один запрос. Второй запрос блокируется, пока переключатель не освободится. Можно показать, что сеть с s ступенями может использоваться для соединения 2s модулей. В этом случае существует только один путь от модуля Q j, к модулю Q j. Таким образом, сеть обеспечивает соединение между двумя произвольными модулями. Однако она не в состоянии одновременно обслуживать большое количество запросов. Например, соединение между точками Q 0 и Q 4 может быть установлено одновременно с соединением между точками Q 1 и Q 5.
Рис. 10.6. Многоступенчатая сеть типа shuffle Многоступенчатая сеть дешевле сети с координатной коммутацией. Для соединения n узлов по схеме, показанной на рис. 10.6, необходимо s =log2n ступеней с n/2 переключателями на каждой. Передача запроса по сети выполняется следующим образом. Источник направляет в сеть двоичную последовательность, представляющую адрес приемника. Эта последовательность передается по сети, и на каждой ступени анализируется очередной ее бит, который определяет состояние переключателя. В нашем примере на ступени 1 используется старший бит, на ступени 2 — средний бит, а на ступени 3 — последний, младший бит. Когда запрос поступает на один из входов переключателя, он маршрутизируется к верхнему выходу, если управляющий бит имеет значение 0, или к нижнему выходу в противном случае. Обратите внимание на пример, приведенный на рис. 10.6, где жирной линией показан маршрут следования по сети запроса от источника Q 5 приемнику Q 3. Этот маршрут определяется двоичной последовательностью 011, составляющей адрес приемника. Сети с топологией гиперкуба Во всех трех описанных выше коммутационных схемах передача запросов между двумя модулями происходит с некоторой задержкой. Эти схемы могут использоваться для реализации мультипроцессоров типа UMA. Далее мы рассмотрим топологии, подходящие только для мультипроцессоров типа NUMA. Первая и наиболее популярная сеть этого типа, соединяющая 2n узлов, имеет топологию n-мерного куба, называемую гиперкубом (hypercube). Помимо коммуникационных схем каждый узел обычно содержит процессор и модуль памяти, а также некоторые средства ввода-вывода. На рис. 10.7 изображен трехмерный гиперкуб. Здесь кружочками обозначены коммуникационные схемы узлов. Соединяемые узлами функциональные устройства на рисунке не показаны. Ребра куба представляют собой двунаправленные связи между соседними узлами. В n-мерном гиперкубе каждый узел непосредственно связан с n соседними узлами. Двоичные адреса узлам удобнее назначать таким образом, чтобы адреса двух соседних узлов отличались единственным битом, как на рис. 10.7. Маршрутизация сообщений в гиперкубе выполняется очень просто. Передача сообщения от процессора в узле Ni процессору узла Nj происходит следующим образом. Сначала двоичные адреса источника i и приемника j сравниваются, начиная с младшего бита и заканчивая старшим. Предположим, что они отличаются разрядом р. Далее узел Ni передает сообщение своему соседу, адрес которого, k, отличается от i в разряде p. Узел N k пересылает сообщение своему соседу, используя ту же схему сравнения адресов. После каждой передачи от одного узла к другому сообщение приближается к узлу-приемнику N j. Например, для передачи сообщения от узла N2 к узлу N5 требуются 3 пересылки, осуществляемые через узлы N3 и n1. Причем именно это количество пересылок соответствует максимальному расстоянию, проходимому сообщением в n-мерном гиперкубе. Рис. 10.7. Сеть в виде трехмерного гиперкуба Сканирование адресов назначения в направлении справа налево не является единственным методом маршрутизации сообщений. Может использоваться любая другая схема, при которой с каждой пересылкой от узла к узлу сообщение приближается к месту назначения, а для дальнейшей маршрутизации на каждом узле используется только локальная информация. Если кратчайший путь передачи сообщения не доступен, оно может быть направлено по более длинному пути. Однако при этом следует избегать зацикливания, когда сообщение проходит по замкнутому маршруту и возвращается к исходной точке, так и не достигнув места назначения. Сети с топологией гиперкуба используются во множестве систем. Сети с ячеистой топологией Одним из самых удобных способов соединения большого количества узлов является ячеистая сеть (mesh network). Пример ячеистой сети с 16 узлами приведен на рис. 10.8. Соединения между ее узлами являются двунаправленными. Такие сети завоевали популярность в начале 1990-х годов и стали быстро вытеснять гиперкубические структуры в архитектуре крупных мультипроцессорных систем. Рис. 10.8. Двухмерная ячеистая сеть Маршрутизация в ячеистой сети может осуществляться несколькими способами. Один из простейших и наиболее эффективных способов выбора пути между источником N i и приемником N j, заключается в том, что сначала выполняется передача данных в горизонтальном направлении от узла N i к узлу N j. По достижении столбца, в котором расположен узел N j, пересылка производится по вертикали. Широко известными примерами мультипроцессорных систем с ячеистой топологией являются компьютер Paragon компании Intel и экспериментальные системы Dash и Flash, разработанные в Стэндфордском университете, а также система Alewife, созданная в Массачуссетском технологическом институте. Если соединить между собой узлы, находящиеся на противоположных сторонах (рис. 10.8), получится сеть, состоящая из набора двунаправленных горизонтальных колец, соединенных с такими же вертикальными кольцами. В подобных сетях, то есть имеющих тороидальную топологию (torus), значительно сокращается среднее время передачи информации, правда, они сложнее и дороже. Сеть такого типа используется в системах АР3000 компании Fujitsu. Как обычную, так и тороидальную ячеистую схему можно реализовать в виде трехмерной сети с соединениями между соседними узлами в направлениях Х, Y и Z. Трехмерная тороидальная сеть используется, в частности, в мультипроцессоре Cray T3E. Сети с древовидной топологией Еще одной популярной топологией сети обмена является иерархически структурированная сеть в виде дерева. На рис. 10.9, а показано дерево, соединяющее 16 модулей. Каждый родительский узел этого дерева позволяет соединять по два дочерних узла за раз. Узлы промежуточных уровней, такие как узел А, могут соединять один из дочерних узлов с родительским. Таким образом осуществляется взаимодействие между двумя удаленными узлами. Через один узел дерева не может одновременно проходить несколько соединений. Древовидная сеть хорошо подходит для случаев, когда через корневой узел сети проходит небольшой трафик. Если же трафик возрастает, производительность сети резко снижается, поскольку корневой узел становится ее узким местом. Для повышения пропускной способности сети с древовидной структурой можно увеличить количество соединений на верхних уровнях иерархии. В результате получается толстое дерево (fat tree), где каждый узел имеет более одного родительского узла. Пример сети с топологией толстого дерева показан на рис. 10.9, б. Здесь каждый узел имеет два родительских узла. Подобная сеть использовалась в системе СМ-5 производства Thinking Machines Corporation. а б Рис. 10.9. Древовидные сети: дерево с четырьмя ветвями (а); толстое дерево (б) Сеть с кольцевой топологией Одной из простейших сетевых топологий является кольцевое соединение всех узлов системы (рис. 10.10, а). Главное преимущество такой структуры состоит в простоте ее реализации. Соединения в кольце могут быть достаточно широкими, благодаря чему по ним можно параллельно передавать целый пакет. А вот слишком длинные кольца не эффективны, поскольку среднее время передачи информации между двумя узлами получается слишком большим. Сети с кольцевой топологией могут служить строительными блоками в топологиях, описанных в предыдущих разделах, в частности в ячеистых, древовидных сетях и гиперкубах. Рассмотрим такой простой пример. При использовании колец в древовидной структуре получается иерархия, показанная на рис. 10.10, б. На этом рисунке изображена двухуровневая иерархия, но возможно и большее количество уровней. В случае использования нескольких маленьких колец вместо одного большого уменьшается задержка при передаче сообщения в пределах кольца, а также задержка во время передачи данных между соседними кольцами. Недостатком этой схемы является то, что кольца верхних уровней нередко становятся узким местом сети, задерживающим значительную часть трафика. а б Рис. 10.10. Сеть с кольцевой топологией: одно кольцо (а); иерархия колец (б) Сети смешанной топологии Мы рассмотрели несколько сетевых топологий и попытались описать достоинства и недостатки каждой из них. Разработчики мультипроцессорных систем стараются добиться максимальной производительности за приемлемую стоимость. Поэтому во многих коммерческих системах используются смешанные топологии — их разработчики постарались соединить достоинства нескольких топологий в единой системе. Например, отличным способом объединения нескольких процессоров является комбинация шинной топологии и топологии с координатной коммутацией. Часто встречаются процессорные кластеры, обычно содержащие от 2 до 8 процессоров, соединенные шиной или координатным коммутатором. Такие кластеры выступают в роли узлов сети, объединенных в большую систему с помощью подходящей топологии. В системе AV25000 производства Data General используются кластерные узлы, процессоры которых связаны общей шиной. В единую сеть эти узлы соединяются по кольцевой схеме. В системе Exemplar V2600 производства Hewlett-Packard узлы тоже соединены при помощи кольцевой сети, а процессоры в каждом из них объединены между собой посредством координатного коммутатора. В системе AlphaServer SC производства Compaq узлы сети соединяются в толстое дерево, а процессоры внутри узлов соединены путем координатной коммутации. Симметричные мультипроцессорные системы Рассмотрим мультипроцессорную систему, в которой все процессоры имеют одинаковые возможности доступа к модулям памяти и устройствам ввода-вывода, так что с точки зрения операционной системы процессоры являются абсолютно идентичными. Если любой из процессоров может выполнять и ядро операционной системы, и пользовательские программы, система называется симметричной мультипроцессорной системой (Symmetric Multiprocessor, SMP). В такой системе любой процессор может обрабатывать внешние прерывания и инициировать операцию ввода-вывода для любого устройства ввода-вывода. Симметричные мультипроцессорные системы обычно реализуются на основе шинной сети или сети с координатной коммутацией. Они часто используются в качестве узлов более крупных мультипроцессорных систем. Например, узлы SMP входят в состав описанных выше мультипроцессоров Exemplar V2600 и AlphaServer SC. 10.5. Организация памяти в мультипроцессорных системах В разделе 6 было показано, какое большое влияние на производительность оказывает организация памяти в однопроцессорной системе. Сказанное верно и для мультипроцессорных систем. Для того чтобы использовать свойство локализации ссылок, в каждый процессор обычно включают первичный и вторичный кэши. Если система построена так, как на рис. 10.2, каждый процессорный модуль может быть соединен с коммуникационной сетью способом, показанным на рис. 10.11. На этом рисунке изображен только вторичный кэш, поскольку мы считаем, что первичный кэш интегрирован в микросхему процессора. При обращении к модулям памяти используется глобальное адресное пространство, в котором каждому модулю назначен свой диапазон физических адресов. В такой системе с общей памятью процессоры имеют равный доступ ко всем модулям памяти. С точки зрения программного обеспечения это простейший способ использования адресного пространства. Рис. 10.11. Процессорный узел в мультипроцессорной системе, показанной на рис. 10.2 В мультипроцессорных системах типа NUMA (рис. 10.3) каждый узел содержит процессор и модуль памяти. Наиболее естественный способ реализации такого узла показан на рис. 10.12. Для подобных систем удобно использовать глобальное адресное пространство. И снова каждый процессор может обратиться к любому модулю памяти, хотя на доступ к локальным модулям памяти глобального адресного пространства уходит меньше времени, чем на доступ к удаленным модулям. В системе с распределенной памятью (рис. 10.4) процессоры могут обращаться напрямую только к своей локальной памяти. Поэтому каждый модуль памяти составляет локальное адресное пространство одного процессора; глобального адресного пространства нет вообще. Любое взаимодействие между программами или процессами, выполняющимися на разных процессорах, осуществляется при помощи сообщений, передаваемых между процессорами. При таком виде взаимодействия каждый процессор рассматривает коммуникационную сеть как устройство ввода-вывода. В таком случае каждый узел системы можно рассматривать как отдельный компьютер. Поэтому системы подобного типа также называются мультикомпьютерными. Данная архитектура представляет собой простейший способ соединения множества компьютеров в большую систему. Взаимодействие между задачами, выполняющимися на разных компьютерах, осуществляется довольно медленно, поскольку для обмена сообщениями требуется программное обеспечение. Этот тип систем рассматривается в разделе 10.7. Рис. 10.12. Структура узла мультипроцессора, изображенного на рис. 10.3
Когда одни и те же данные используются множеством процессоров, необходимо гарантировать, что все процессоры будут работать с одними и теми же значениями элементов данных. В связи с этим наличие множества кэшей в системе с общей памятью составляет серьезную проблему. В разных кэшах могут находиться разные копии одних и тех же данных. Когда процессор изменяет элемент данных в собственной кэш-памяти, это изменение должно быть внесено во все остальные кэши, в которых имеются копии этих данных. Или же все остальные копии должны быть помечены как недостоверные. Иными словами, необходимо, чтобы общие данные были согласованы (когерентны) во всех кэшах системы. Самое распространенное решение этой проблемы мы рассмотрим в разделе 10.6.2. 10.6. Программный параллелизм и общие переменные Во введении к этой главе говорилось, что сложную задачу не всегда легко разбить на параллельно выполняемые подзадачи. Однако есть особые случаи, когда это сделать достаточно просто. В частности, если главная задача представляет собой набор независимых программ, эти программы легко выполнить на разных процессорах. И если программы не блокируют друг друга, соревнуясь за устройства ввода-вывода, мультипроцессор оказывается полностью загруженным. Кроме того, программу легко разделить на параллельно выполняемые задачи при использовании языка высокого уровня, позволяющего программисту явно выделить отдельные задачи. Такая конструкция часто называется PAR-сегментом. Она показана на рис. 10.13. Между управляющими командами PARBEGIN и PAREND находится список процедур, от Proc1 до ProcК, которые могут выполняться параллельно. Рассмотрим порядок реализации этой программы. После завершения сегмента программы, предшествующего команде PARBEGIN, может немедленно начаться выполнение любой из К параллельных процедур или же всех этих процедур, что зависит от количества свободных процессоров. Последовательность их запуска может быть любой. Выполнение части программы, следующей за командой PAREND, разрешается только после завершения выполнения всех или К параллельных процедур. PARBEGIN Proc1; Proc2; ….. PAR-сегмент ProcК; PAREND ….. Рис. 10.13. Программная конструкция для параллельного выполнения
Если мультипроцессорная система выполняет только эту программу, за эффективное использование процессоров отвечает программист. Степенью параллелизма PAR-сегментов К, и отношением их общего размера к размеру последовательных сегментов определяется эффективность работы мультипроцессорной системы. Наиболее эффективное использование мультипроцессорных систем достигается путем применения компиляторов, способных автоматически определять фрагменты пользовательских программ, которые можно запускать параллельно. Программист обычно представляет программу как набор последовательно производимых операций. Но, несмотря на это, существует много возможностей параллельной реализации различных групп команд. Простейшим примером является многократно выполняемый программный цикл. Если данные, используемые на разных итерациях, независимы, итерации можно осуществлять параллельно. Если же при первом прохождении по циклу генерируются данные для второго прохождения и т. д., параллельная работа не возможна. Компилятор должен выявлять зависимости по данным и решать, какие операции можно выполнить параллельно, а какие — нельзя. Разработка компиляторов, разбивающих программу на параллельно выполняемые фрагменты, — задача не из простых. И даже после того, как такие фрагменты будут выделены, их еще нужно оптимально распределить между процессорами, так как свободных процессоров может быть меньше, чем фрагментов. Мы не будем обсуждать вопрос распределения подзадач между процессорами и планирования последовательности их реализации, а лишь поговорим о доступе к общим переменным, которые модифицируются параллельно выполняемыми подзадачами в мультипроцессорной системе. 10.6.1. Доступ к общим переменным Предположим, что мы определили две задачи, которые могут параллельно выполняться мультипроцессорной системой. Эти задачи почти полностью независимы, но время от времени они считывают и модифицируют некоторую общую переменную, хранящуюся в глобальной памяти. Пусть, например, общая переменная SUM представляет баланс некоторого счета. Этот счет должен обновляться несколькими задачами, выполняющимися разными процессорами. Каждая задача производит с переменной SUM следующие действия: считывает ее текущее значение, выполняет некоторую операцию с его использованием, а результат сохраняет в переменной SUM. Нетрудно представить себе, какие ошибки могут возникнуть, если такие операции с переменой SUM будут осуществляться задачами Т1 и Т2, выполняющимися в параллельном режиме процессорами Р1 и Р2. Предположим, что обе задачи, Т1 и Т2, считывают текущее значение переменной SUM, скажем 17, и каждая по отдельности его модифицирует. Задача Т1 прибавляет к нему 5, получая 22, а задача Т2 вычитает из него 7, результатом чего является число 10. Затем каждая из задач заносит в переменную SUM свой результат — сначала это действие выполняет задача Т2, затем задача Т1. Теперь в переменной SUM хранится число 22, что является ошибкой, так как на самом деле в этой переменной должно находиться значение l5 (17 +5-7), которое получится при строго последовательном проведении изменений. Для того чтобы обеспечить правильную работу с переменной SUM, каждая задача должна получать к ней монопольный доступ на все время выполнения последовательности операций чтения, модификации и записи. С этой целью может быть задействована глобальная переменная блокировки LOCK и машинная команда Test and Set. Переменная LOCK может принимать значение 0 или 1. Мы используем ее для того, чтобы гарантировать, что никакие две задачи не смогут одновременно получить доступ к переменной SUM. Последовательность команд, для выполнения которой требуется монопольный доступ к некоторой переменной, называется критической секцией прог
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|