Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Суперкомпьютеры и системы. Мультипроцессоры. Учебное пособие

.pdf
Скачиваний:
1
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
го элемента данных и является ли она «чистой» или «грязной» (моди­фицированной). Поскольку запрашивать каталог приходится при вы­полнении любого обращения к памяти, он должен поддерживаться вы­сокоскоростным специализированным аппаратным обеспечением, спо­собным обработать запрос очень быстро. На рис. 3.10 показана струк­тура однопроцессорного узла cc-NUMA-системы, построенной на ос­нове использования метода каталога.
Адресное пространство всей системы распределено между узлами, и это распределение должно быть «известно» диспетчеру памяти. Са­мый удобный и простой вариант, когда количество узлов в системе равно степени двойки и память распределена поровну между узлами. Тогда старшие разряды любого адреса памяти являются номером узла.
При любом обращении к памяти диспетчер по локальной шине от­слеживает вырабатываемый процессором адрес и результат обработки этого обращения локальным кэшем. Вначале рассмотрим только опе­рации чтения данных. Будем далее обозначать узел, запрашивающий чтение элемента данных, как УЗ, а узел-владелец, в основной памяти которого элемент данных хранится постоянно, как УВ, и узел, в кэше которого находится копия значения или модифицированное значение элемента, как УК.
Рис. 3.10. Узел cc-NUMA-системы на основе каталога
Процессор
Каталог
Локальный
кэш
Диспетчер
памяти
Коммутатор
Модуль
памяти
узла
Модуль
памяти
узла
Если требуемый элемент данных находился в локальном кэше (по­падание в кэш), то кроме передачи его значения в процессор больше
41
ничего не делается. При промахе кэша диспетчер по старшим разрядам адреса определяет, какой узел является владельцем элемента данных, и выбирает сведения о его фактическом местонахождении из каталога этого узла (нужный каталог может находиться прямо в запрашиваемом узле, т. е. УЗ может совпадать с УВ).
Значение требуемого элемента данных может находиться либо в основной памяти узла-владельца, либо, если оно было ранее выбрано (а потом, возможно, модифицировано) каким-либо процессором, в кэше некоторого узла УК. Заметим, что возможна и такая ситуация, когда владелец одновременно хранит и копию в кэше, т. е. УВ совпа­дает с УК.
В первом случае наряду с выборкой сведений из каталога из основ­ной памяти узла-владельца по заданному адресу выбирается значение элемента и отправляется в запрашивающий узел. Во втором случае за­прос перенаправляется в узел УК, который хранит модифицированное значение. Из его кэша значение выбирается и через коммуникацион­ную сеть передается в УЗ. В любом случае в каталоге узла-владельца УВ делается отметка, что копия значения элемента теперь находится в кэше узла УЗ. Это делается согласно принципу локальности: замечено, что если процессор читает некоторую переменную, то с высокой веро­ятностью он вскоре будет читать ее заново либо вскоре выполнит за­пись нового ее значения. В этих случаях операции повторного доступа к элементу данных будут выполнены быстрее, если элемент находится в локальном, а не в удаленном кэше.
Пусть теперь процессор выполняет операцию записи нового значе­ния в память. Согласно тому же принципу локальности элемент дан­ных должен попасть прежде всего в локальный кэш УЗ, даже в том случае, если при попытке записи обнаружен кэш-промах. В этом слу­чае диспетчер памяти определяет, какая строка кэша должна быть вы­теснена. Наилучшим кандидатом является любая из недействительных строк, становящаяся теперь актуальной. Недействительными становят­ся все строки в момент включения электропитания системы и те стро­ки, актуальные значения которых оказались в кэшах других узлов. Не­действительная строка переводится в состояние актуальной, в нее пи­шется адрес основной памяти элемента данных. Отметим, что в случае кэш-попадания при записи актуальная строка в кэше уже есть. Далее в эту строку записывается новое значение элемента данных, а во все уз­лы системы рассылается сообщение о том, что этот узел стал УК по отношению к элементу с этим адресом. Диспетчеры всех узлов прове-
42
ряют свои каталоги и кэши по этому адресу. Возможны следующие ситуации.
1. Узел является владельцем элемента. В его каталоге отмечается, какой из узлов теперь стал УК, эта информация будет далее использо­ваться при любом чтении так, как описано выше.
2. Узел хранит в локальном кэше предыдущее значение элемента данных. Эта строка кэша диспетчером памяти узла превращается в не­действительную и может использоваться для любой последующей операции записи так, как описано выше.
3. Узел не является владельцем и не хранит копию. В этом случае его диспетчер не делает ничего.
Если при кэш-промахе по записи в кэше нет ни одной недействи­тельной строки, то диспетчер памяти узла выбирает одну из строк, хранящую немодифицированную копию значения какого-либо элемен­та (по возможности, если строки хранят информацию о времени, ис­текшем с момента последнего обращения к этой строке, – самую ста­рую). И, наконец, если все строки кэша хранят модифицированные значения каких-либо элементов, то диспетчер памяти решает, какая из них будет вытеснена в основную память. Решение может приниматься, например, на основании «близости» узла-владельца этого элемента к данному узлу по коммуникационной среде. Идеальным будет случай, когда вытеснять надо в собственный модуль памяти, не загружая этим коммуникационную среду системы в целом. Содержание выбранной строки вместе с адресом передается в нужный узел, а выбранная стро­ка теперь будет хранить модифицированное значение элемента дан­ных. Об этом извещаются все узлы системы.
Размер памяти каталога каждого узла зависит от соотношения объ­ема модуля памяти узла и размера строки кэша. Размер строки кэша определяется шириной шины данных коммуникационной среды си­стемы (или, наоборот, требует, чтобы ширина шины данных совпадала с размером строки кэша в битах). Иначе, если ширина шины будет меньше размера строки кэша, передача строки от узла к узлу должна выполняться за несколько циклов работы коммуникационной среды. При этом должны учитываться еще и ширина локальной шины узла (максимальное количество бит данных, читаемых / записываемых про­цессором за одну операцию обращения к памяти). Кроме того, следует принимать во внимание еще один аспект принципа локальности: если процессор обратился к памяти по адресу A, то с высокой вероятностью в ближайшее время обратится к ней по адресу A + 1. В то же время
43
чрезмерно увеличивать размер строки не следует, поскольку в некото­рых случаях после обращения к элементу данных с адресом A не по­следует обращений к памяти по ближайшим последующим адресам. Следовательно, слишком широкая строка кэша неизбежно повлечет за собой лишние, паразитные, пересылки тех данных, которые никому не понадобятся. Типичным компромиссом можно считать размер элемента данных строки, равный 64 байтам. Заметим при этом, что кэш-промах при записи может повлечь за собой выполнение операции чтения строки целиком из памяти или кэша другого узла в том случае, если процессор работает с данными меньшего размера, чем размер строки.
Размер одной записи каталога k в битах определяется количеством
k
K ≤ 2
узлов в системе (или, наоборот, ограничивает его). Чем больше емкость модуля памяти и чем меньше размер строки кэша, тем боль­шее количество записей должен хранить каталог. Если модуль памяти узла имеет емкость 2
N
байт, а строка кэша хранит 2n байт, то каталог должен хранить N/n записей. Например, при N = 30 (емкость модуля памяти 1 Гбайт) и n = 6 (64 байта данных в строке) каталог должен иметь 2
30
/ 26 = 224 = 16 777 216 записей. В этом случае для системы с количеством узлов, меньшим или равным 256, в каждом узле нужно иметь быстродействующую память объемом 16 Мбайт; если же коли­чество узлов превышает 256, то объем этой памяти узла должен быть равен 32 Мбайт.
Очевидным недостатком этого простейшего метода является то, что любой элемент данных может быть кэширован только одним уз­лом. Это будет вызывать, точно так же как в UMA-системах, массу не­нужных дополнительных пересылок данных по коммуникационной среде. Чтобы строки можно было кэшировать в нескольких узлах, тре­буется расширить каждую запись каталога и усовершенствовать спо­соб поиска узлов (для того чтобы объявлять недействительными или обновлять при записи). Возможны различные варианты. Один из вари­антов – содержать в каждой записи каталога m полей для идентифика­ции других узлов, что позволит кэшировать каждую строку на не­скольких узлах (до m узлов). Второй вариант – заменить поле номера узла битовой картой, по одному биту на узел. Здесь нет ограничений на количество копий, но существенно растут непроизводительные за­траты. Для каждого узла каталог, содержащий 256 бит для 64-байтной (512-разрядной) строки кэша, потребует уже 512 Мбайт быстродей­ствующей памяти. Третий вариант – хранить в каждой записи каталога 8-разрядное поле и использовать его в качестве заголовка связного
44
списка, содержащего указатели на все копии строки кэша в разных уз­лах. Размеры списков могут быть разными для разных записей. При такой стратегии также требуется много дополнительного пространства в быстродействующей памяти на каждом узле для указателей связного списка. Кроме того, требуется просматривать список, чтобы искать указатель на модифицированную копию, которого может и не быть в списке. Каждая из трех стратегий имеет свои достоинства и недо­статки, и все три стратегии применяются на практике в реальных cc-NUMA-системах.
У данной схемы есть еще одна проблема: как проверять, обновлена исходная память или нет? Если нужно считать строку кэша, которая не изменялась, запрос может быть удовлетворен из основной памяти, и при этом не нужно направлять запрос в кэш. Если же требуется считать из­мененную строку кэша, запрос должен быть направлен в тот узел, в ко­тором находится эта строка кэша, поскольку только здесь имеется ее действительная копия. Если же разрешается иметь только одну копию строки кэша, то контролировать изменения в строках кэша нет никакого смысла, поскольку любой новый запрос требует передачи сообщения в кэш, хранящий существующую копию, чтобы объявить ее недействи­тельной. Естественно, для хранения информации о состоянии каждой строки кэша («чистая» или «грязная») требуются дополнительные биты, и нужно информировать диспетчер памяти узла-владельца о каждом изменении строки кэша, даже если существует только одна копия этой строки. Если же таких копий несколько, то изменение одной из них означает необходимость объявления всех остальных недействительны­ми, поэтому нужен эффективный протокол, позволяющий избежать си­туации гонок (т. е. возникновения различных копий значения одного и того же элемента данных). Например, чтобы изменить совместно ис­пользуемую строку кэша, один из держателей этой строки перед ее из­менением должен был бы запросить у узла-владельца монопольный до­ступ к ней. Такой запрос означал бы объявление всех остальных копий недействительными.
Подобную технологию обеспечения когерентности кэшей реализу­ет, например, широко распространенный интерфейс SCI (Scalable Coherent Interface), предназначенный для достижения высоких скоро­стей доступа к разделяемой памяти с малым временем задержки. SCI представляет собой комбинацию шины и локальной сети, обеспе­чивает реализацию когерентности кэш-памяти, размещаемой в узлах, посредством механизма распределенных каталогов.
45
Существует большое количество различных реализаций архитекту­ры cc-NUMA: SGI Origin 2000, SGI Origin 3000, Cray ТЗЕ, HP Convex Exemplar, IBM/Sequent NUMA-Q 2000, HP Superdome… При их созда­нии преследовалась одна цель – построить масштабируемый мульти­процессор высокой производительности с общей памятью. Основные различия между системами этого класса заключаются в способах под­держания когерентности кэшей в пределах всей вычислительной си­стемы – snooping / snarfing, directory или snooping / snarfing & directory. Кроме того, различающим признаком является принцип построения и топология коммуникационной сети, связывающей узлы.
3.2.3. COMA-СИСТЕМЫ
COMA (Cache Only Memory Architecture) – это такая архитектура системы, в которой локальная память каждого процессора считается частью большой общей кэш-памяти. Других видов памяти нет. Это требует перемещения элемента данных (а не копии его значения) тому процессору, который его затребовал. В COMA отсутствует иерархия памяти, а адресное пространство является объединением адресных пространств всех кэшей.
Принципиальная особенность концепции COMA выражается в ди­намике. Здесь любой элемент данных не привязан статически к како­му-либо модулю памяти, хотя и имеет уникальный адрес, остающийся неизменным в течение всего времени существования переменной. Просто любое значение вместе с его адресом всегда хранится в един­ственном кэше. Перенос данных из одной локальной кэш-памяти в другую не требует участия операционной системы, но предполагает участие сложной и дорогостоящей аппаратуры управления памятью, очень похожей (но не в точности совпадающей) с диспетчером памяти cc-NUMA-систем. Для организации такого режима используют так называемые справочники (directory), хранящие информацию о теку­щем расположении всех элементов данных.
Наиболее быстродействующий, но и самый дорогой вариант реали­зации – размещение в каждом узле полной копии справочника. Каждая запись такого справочника – это адрес элемента данных и номер узла, хранящего его значение. Когда процессор обращается к локальному кэшу для выборки / модификации какого-либо элемента данных, то при кэш-попадании ни коммуникационная сеть, ни другие узлы не привле­каются. Если же обнаруживается кэш-промах, то диспетчер памяти это-
46
го узла выбирает из своего справочника номер узла – текущего владель­ца требуемого элемента и через коммуникационную сеть запрашивает перемещение элемента в свой кэш. В этот момент в каждом узле коррек­тируется запись с адресом этого элемента данных, в нее пишется новый номер узла-владельца. На каждый кэш-промах требуется затратить не менее двух циклов работы коммуникационной сети и дополнительно цикл записи элемента данных с его адресом в кэш нового владельца.
Более дешевый, но и менее быстродействующий вариант – распре­деление записей справочника по узлам. В этом случае при кэш­промахе диспетчер памяти по старшим разрядам адреса элемента дан­ных определяет, в справочнике какого узла хранится запись с номером текущего владельца, и по коммуникационной сети отправляет ему за­прос. Это узел по хранящейся в нем информации формирует и отправ­ляет текущему владельцу требование на перемещение элемента дан­ных нуждающемуся в нем узлу. В этом варианте на каждый кэш­промах потребуется затратить не менее трех циклов работы коммуни­кационной сети.
Строка кэша бывшего владельца после перемещения элемента дан­ных в кэш нового владельца становится недействительной. Ясно, что именно недействительные строки будут использоваться диспетчером памяти узла для размещения элементов данных, перемещаемых в этот узел по запросам его процессора. Однако, в принципе, может возник­нуть ситуация, при которой в принимающем данные кэше нет ни од­ной недействительной строки. В ранее рассмотренных системах кон­троллер кэша обеспечивает вытеснение какой-либо строки кэша в соб­ственный модуль основной памяти. Однако в COMA-системе основной памяти нет. Логика диспетчера памяти должна обеспечить взаимодей­ствие с одним или несколькими другими узлами (в предельном слу­чае – со всеми) для обнаружения узла, имеющего хотя бы одну недей­ствительную строку и принудительное перемещение вытесняемой строки в его кэш. На это потребуется заранее неизвестное количество циклов работы коммуникационной сети.
Еще одна неприятная ситуация возникает, если один и тот же эле­мент данных требуется попеременно двум или более процессорам. Этот блок должен перемещаться между узлами туда и обратно при каждой операции доступа, существенно загружая коммуникационную сеть. Бороться с такими проблемами в архитектуре COMA можно только путем правильного распределения вычислительных работ меж­ду процессорами, выполняемого программным обеспечением.
47
Архитектура COMA была реализована в целом ряде систем, в част­ности, в системах с названиями KSR-1 (Kendall Square Research) и DDM (Data Diffusion Machine), однако существенного развития не по­лучила, как и все NUMA-системы. Основной причиной этого явилась недостаточно высокая масштабируемость мультипроцессоров с общей разделяемой памятью при довольно высокой удельной стоимости каж­дого гигафлопа. Максимальное количество процессоров в таких систе­мах не превышает тысячи. При быстродействии одного процессора
9
10
…1010 операций в секунду это приводит к пределу со значением
примерно 10
12
…1013 операций в секунду.
48
4. ГРАФИЧЕСКИЕ ПРОЦЕССОРЫ
И ВЫЧИСЛИТЕЛЬНЫЕ АКСЕЛЕРАТОРЫ
Графические процессоры и вычислительные акселераторы являются мощными средствами увеличения производительности компьютеров (или вычислительных узлов суперкомпьютера), в состав которых они интегрированы. И те и другие обычно представляют собой вычисли­тельные устройства, созданные на основе одного специального чипа и реализующие высокопараллельную обработку данных. Принципы, за­ложенные в основу этой обработки, могут быть различными. Объедине­ние центральных, как правило многоядерных, процессоров с этими устройствами создает гетерогенную вычислительную систему, показан­ную на рис. 4.1.
Рис. 4.1. Структура гетерогенной вычислительной системы
49
Основной компьютер системы, показанный на рисунке справа и названный как Host, управляет несколькими вычислительными устрой­ствами (Compute Device). Каждое такое устройство, в свою очередь, со­держит набор относительно независимых друг от друга вычислителей (Compute Unit), в составе которых работает несколько обрабатывающих элементов (Processing Element).
4.1. ГРАФИЧЕСКИЕ ПРОЦЕССОРЫ
Эти ускорители вычислений представляют собой развитие и моди­фикацию архитектуры ОКМД (один поток команд, много потоков дан­ных). Основные отличия принципов работы графических процессоров от базовых идей архитектуры ОКМД состоят в следующем:
вместо принципа «один поток команд» реализуется принцип «одна программа, исполняемая несколькими ОКМД-подсистемами в чистом виде, работающими каждая в своем темпе»;
аппаратура графического процессора позволяет организовывать исполнение огромного по сравнению с обычным многоядерным ком­пьютером количества легковесных потоков управления, обрабатыва­ющих каждый свои собственные данные;
выполняемая графическим процессором программа (обычно называемая ядром) рассматривается как совокупность блоков потоков, каждый из которых целиком исполняется одной ОКМД-подсистемой;
блоки потоков и потоки в блоках при запуске ядра могут быть организованы в одно-, двух- или трехмерные структуры, что позволяет достаточно просто адаптировать алгоритмы вычислений к природе решаемой задачи;
кроме общедоступного для всей совокупности потоков блока ос- новной памяти (обычно называемого глобальной памятью устройства) каждая ОКМД-подсистема имеет еще несколько уровней памяти с раз­ным быстродействием и разной степенью доступности для исполняе­мых ею блоков и потоков управления.
Графические процессоры в качестве средств высокопроизводи­тельных вычислений появились как результат развития, совершенство­вания и конкуренции видеоадаптеров, выпускаемых основными ком­паниями-производителями – фирмами NVIDIA и AMD (ATI). Вначале в видеоадаптеры с целью разгрузки центральных процессоров от вы­полнения рутинных операций переносились простейшие функции об­работки графической информации. Сама природа задач компьютерной графики – однотипная обработка большого количества точек на плоско-
50