
В.С. Волин, С.А. Черепанов, Н.А. Щербина (ЗАО «МЦСТ»)
Vladimir Volin, Sergey Cherepanov, Nikolay Shcherbina
ОРГАНИЗАЦИЯ ПОДДЕРЖКИ КОГЕРЕНТНОСТИ В СИСТЕМЕ НА КРИСТАЛЛЕ «МЦСТ-R1000»
CACHE COHERENCE SUPPORT IN MCST-R1000 SYSTEM-ON-CHIP
Система на кристалле (СнК) «МЦСТ-R1000» (в процессе проектирования обозначалась «МЦСТ-4R») включает четыре суперскалярных процессорных ядра, реализующих девятую версию системы команд SPARC, общую кэш-память второго уровня и интегрированный северный мост. Каждое процессорное ядро содержит кэш-памяти первого уровня для команд и данных. На базе СнК могут строиться вычислительные системы, включающие до четырех микросхем «МЦСТ-R1000», совместно содержащих до 36 устройств кэш-памяти. Одной из важнейших задач при построении подобной системы является обеспечение согласованности данных. Описанию ее решения посвящена данная статья.
Ключевые слова: система на кристалле, СнК, интегрированный северный мост, когерентность кэш-памятей, протокол когерентности, SPARC, ccNUMA, MOESI.
MCST-R1000 SoC integrates 4 supercalar SPARC V9 cores, shared L2 cache and northbridge on a single die. Each core contains separate L1 instructions and data caches. Systems consisting of up to four MCST-R1000 SoCs can be built. Such systems can contain up to 36 cache memories. One of the biggest challenges in constructing such a system is to provide support for cache coherency. This article is a attempt to describe how MCST-R1000 SoC overcomes this challenge.
Keywords: system on chip, SoC, integrated northbridge, cache coherence, coherence protocol, SPARC, ccNUMA, MOESI.
1. Мировые тенденции в построении многопроцессорных когерентных систем
В 1995 компания Intel представила реализованную в микропроцессоре Pentium Pro технологию Front Side Bus (FSB), предназначенную для построения симметричных многопроцессорных систем с общей памятью (SMP) [1]. FSB была способна обеспечивать взаимодействие до четырех процессоров с контроллером памяти и остальным чипсетом системы. Построение многопроцессорных систем на основе одной шины позволяло обеспечить когерентность (целостность данных разделяемого ресурса памяти, хранящихся в локальных кэшах [1]), используя простые протоколы. Это решение удовлетворяло требованиям на протяжении многих поколений микропроцессоров вплоть до Intel Pentium 4 и до сих пор существует в системах, использующих Intel Atom серию. Подробное изложение технологии FSB и ее использования – в [2].
С ростом производительности процессорного ядра росли требования к пропускной способности канала памяти, что привело к увеличению количества независимых шин при уменьшении числа процессоров, соединенных с одной шиной. В такой ситуации на физическом уровне не исключается возможность «гонок» – одновременной обработки подсистемой памяти нескольких запросов к одному ее блоку (ресурсу) данных, при которой возникает принципиальная проблема обеспечения когерентности. Одновременно с усложнением алгоритмов работы подсистемы памяти возникли сложности физического характера – увеличение скорости передачи данных по одной шине и расширение интерфейсов микросхемы контроллера памяти. Все это привело к необходимости создания принципиально другой технологии построения многопроцессорных систем.
Первая реализованная идея распределенной общей памяти (DSM) была представлена компанией AMD в микропроцессорах семейства Оpteron [1]. На один чип вместе с процессорными ядром (или несколькими ядрами, как в более поздних поколениях Opteron) в составе системы на кристалле интегрируется контроллер памяти, в результате чего образуется вычислительный узел. Это дает возможность создавать сбалансированные многопроцессорные системы. Каждая СнК, добавленная в систему в составе вычислительного узла, за счет своего контроллера привносит дополнительные пропускную способность и объем памяти. Таким образом, решается проблема возрастающей нагрузки на канал памяти с ростом количества процессоров в системе, остро стоящая при использовании FSB.
Многопроцессорные системы на базе процессоров Opteron создаются по принципу соединения «точка-точка» (point-to-point connection) при помощи технологии Hyper Transport. Такое решение позволяет строить кластеры, объединяющие до четырех процессоров, со значительно большей пропускной способностью каналов межпроцессорного обмена, чем в случае шины.
В процессорах семейства Opteron поддержка когерентности реализована путем рассылки широковещательных сообщений во все кэши системы. Гонки при обращениях к подсистеме памяти устраняются отправкой пакетов о завершении операций. Таким образом, на базе процессоров Opteron создаются интегрированные конфигурации с неоднородным доступом к памяти – ссNUMA системы [1]. Более полные сведения о специфике Opteron можно почерпнуть из [3] и [4].
В 2008 году компания Intel представила процессор Xeon 55**серии. Идеи построения многопроцессорных систем на базе Xeon 55** схожи с примененными в Opteron [2]. Объединения СнК осуществляются по принципу «точка-точка» с использованием технологий транспортного уровня Quick Path Intel (QPI).
В последнее время компания Sun Microsystems занимается разработкой процессора Rock, который будет представлять третье поколение процессоров Sun с ярко выраженным многонитевым параллелизмом (Chip Multithreaded Processor, CMT) [1]. В многопроцессорной системе на базе Rock каждая СнК имеет прямое соединение с каждым отдельным чипом контроллера памяти, количество которых больше количества процессоров в системе (в двухпроцессорной системе используются четыре контроллера памяти). Такая организация предоставляет бóльшую пропускную способность памяти, приходящуюся на один процессор, по сравнению с NUMA системой. Из-за отсутствия в CMT-системе прямого межпроцессорного соединения когерентность в ней поддерживается за счет directory based протоколов. Более полное описание этого решения приведено в [6].
2. Реализация когерентного доступа к памяти в ряде микропроцессоров «МЦСТ-R»
Ряд «МЦСТ-R» включает три поколения микропроцессоров: R150, R500 и R500S. Микропроцессоры R150 и R500 были одноядерными и поддерживали построение многопроцессорных систем при помощи общей шины MBus. Эта технология позволяла объединить до четырех процессоров в SMP систему с общим доступом к памяти. Когерентность кэшей в этом случае поддерживалась при помощи отслеживания транзакций на шине (bus snooping).
В СнК «МЦСТ-R500S» на одном кристалле находятся два процессорных ядра с общей кэш-памятью второго уровня L2. Необходимую полосу пропускания памяти обеспечивает встроенный контроллер DDR-памяти, а шина MBus заменена интегрированным коммутатором. Для кэш-памяти первого уровня L1 каждого ядра применена политика сквозной записи (write-through) – когда кэш L2 обрабатывает запись, полученную из одного процессорного ядра, адрес транзакции посылается во второе ядро с целью вытеснения этой строки. Такое решение позволяет поддерживать кэш L1 обоих ядер в когерентном состоянии. Задача объединения нескольких СнК этого типа в систему с распределенной когерентной памятью не ставилась.
3. Общая организация подсистемы памяти СнК «МЦСТ-R1000»
Система на кристалле «МЦСТ-R1000» представляет собой дальнейшее развитие приведенного выше ряда разработок ЗАО «МЦСТ». Ее структура представлена на рис. 1.
В этой микросхеме на один кристалл вместе с процессорными ядрами и кэш-памятью второго уровня L2 интегрирован северный мост NB, который включает:

Рис. 1
Общая структура СнК «МЦСТ-R1000»
(CPU0, …, CPU3 – четыре процессорных ядра; L2 – кэш-память второго уровня; CC – контроллер когерентности; MC – контроллер оперативной памяти; Host Bridge (HB) – мост ввода/вывода; IOCC – контроллер канала ввода/вывода; IPCC – контроллер межсистемного обмена)
Принципиально новым свойством подсистемы памяти здесь является возможность объединения нескольких СнК в когерентный многопроцессорный ccNUMA-кластер при помощи связей типа «точка-точка». Системный коммутатор, IPCC и высокоскоростные LVDS связи образуют сеть на кристалле (Network on Chip, NoC) [7]. Она объединяет абонентов системы, содержащих вычислительные ресурсы, и позволяет им обращаться к ресурсам других абонентов. Топология сети на кристалле определяется на этапе инициализации системы, единственным требованием к реальной физической топологии является ее связность. Абоненты системы способны работать с произвольной топологией, однако ее конкретная конфигурация может существенно сказаться на пропускной способности сети.
Обращение абонента к какому-либо ресурсу системы разбивается на последовательность пакетов, образующих транзакцию. Пакеты, принадлежащие разным транзакциям, передаются независимо друг от друга, что позволяет выполнять несколько транзакций параллельно. В СнК «МЦСТ-R1000» каждый абонент обеспечивает одновременное выполнение до 16 транзакций.
Совокупность изменений привела к пересмотру некоторых решений в подсистеме памяти процессорного ядра. Переход на девятую версию системы команд SPARC, суперскалярная организация, оптимизация конвейера процессорного ядра существенно улучшили производительность по сравнению с предыдущим поколением ядер данной архитектуры. Этот результат и увеличение количества ядер в системе сделали поток вытеснений узким местом системы, поэтому политика записи в кэш-память первого уровня L1 была изменена со сквозной на отложенную (write-back), что существенно сократило поток обращений в L2. Чтобы использовать возросший параллелизм на уровне памяти, кэш L1 сделан неблокирующим (допускает до четырех промахов), реализована программная предвыборка значений в кэш (операция PREFETCH) с возможностью указать кэш-память, в которую должна делаться предвыборка, и желаемое конечное состояние блока.
4. Логическая организация системы
Как отмечалось, вычислительная система на базе СнК «МЦСТ-R1000» может содержать до 36 кэшей. Копия данных может одновременно находиться в нескольких из них. Запись в один кэш приводит к тому, что во всех остальных оказываются устаревшие данные. Когерентное состояние поддерживается при помощи широковещательных сообщений на основе протокола MOESI [1]. Блок в кэш-памяти может пребывать в пяти состояниях:
Исходными запросчиками в системе являются процессорные ядра и мост ввода/вывода HB. Запросы процессорных ядер объединяются в кэш-памяти второго уровня. Если это возможно, запросы процессорных ядер обрабатываются в L2 без обращения к внешним ресурсам, в противном случае через сеть на кристалле происходит рассылка когерентных запросов всем абонентам, содержащим кэш-память.
Абонентами сети на кристалле являются кэш-память второго уровня L2, контроллер когерентности CC и мост ввода/вывода HB. Они распределяют между собой следующие функции:
Приведенные функции распределены между кэшем L2 (источник транзакций и кэш-контроллер), контроллером когерентности (приемник транзакций и контроллер синхронизации), мостом ввода/вывода (источник транзакций, который используется для DMA, и приемник транзакций, обеспечивающий посылку и прием пакетов).
Схема выполнения транзакции когерентного чтения для случая, когда запросчиком является кэш L1 и происходит промах в L2, показана на рис. 2. Кэш L1 посылает запрос (Read request) на выполнение чтения в L2. После проверки тегов и обнаружения промаха кэш L2 посылает пакет, инициирующий транзакцию (Request packet), в контроллер когерентности. Модуль СС, проверив, что не нарушена синхронизация, запускает чтение памяти (Memory read) и посылает широковещательный снуп-запрос (Snoop request packet) во все кэш-контроллеры системы. При обнаружении конфликта обработка нового запроса откладывается до получения пакета, подтверждающего завершение выполнения предыдущего обращения к данному блоку. Далее контроллер MC производит чтение запрашиваемого блока и посылает источнику транзакции пакет с данными из оперативной памяти (Memory read response). Одновременно с этим кэши L2 различных узлов системы получают снуп-запросы и посылают источнику транзакции снуп-ответы (Snoop response packet). После получения всех снуп-ответов и ответа из MC источник транзакции посылает в контроллер когерентности пакет, сигнализирующий о завершении транзакции (Finished at the initiator packet), а запросчику выдает ответ с данными (Read response). Такая транзакция может быть инициирована в результате операций LOAD или STORE для подкачки в кэш L1 необходимого блока данных.

Рис. 2
Схема выполнения транзакции чтения
Схема выполнения транзакции когерентной записи для случая, когда запросчиком является кэш L1 и происходит промах в L2, показана на рис. 3. Кэш L1 посылает запрос на выполнение записи в L2 (Write request). После проверки тегов и обнаружения промаха кэш L2 посылает пакет, инициирующий транзакцию(Request packet), в контроллер когерентности. После проверки синхронизации контроллер когерентности CC посылает инициатору пакет, запрашивающий пересылку записываемых данных и подтверждающий начало исполнения им транзакции (Data request packet). Также контроллер СС посылает широковещательный снуп-запрос (Snoop request packet) во все кэш-контроллеры системы и резервирует ресурсы в контроллере памяти MC. Получив данные для записи (Store data packet), контроллер когерентности передает их в контроллер памяти. После получения всех снуп-ответов (Snoop response packet) кэш L2, инициировавший транзакцию, сообщает запросчику о завершении записи (Write completion notification). Такая транзакция может быть инициирована в результате операции записи блока, входящей в состав системы команд SPARC V9.
Рис. 3
Схема выполнения транзакции записи
5. Кэш-память первого уровня L1
Кэш данных первого уровня (далее L1D) поддерживает все состояния протокола MOESI, в то время как кэш инструкций первого уровня (далее L1I) поддерживает только состояния S и I.
При выполнении процессорным ядром команды LOAD проверяется наличие блока в кэш-памяти L1D. При обнаружении блока в состояниях M, O, E, S данные считываются из L1D, иначе происходит выделение места для блока в L1D, а в L2 отправляется команда чтения блока. При выполнении процессорным ядром команды STORE проверяется наличие блока в кэш-памяти L1D. При обнаружении блока в состояниях M или E данные записываются в L1D и состояние блока меняется на M. При отсутствии блока в кэше L1D (состояние I) происходит выделение места в нем по тому же алгоритму, что и при чтении, а в L2 отправляется команда чтения блока с вытеснением.
Вытеснение блоков из кэша L1 в L2 выполняется специальной командой. При вытеснении команда выдается в L2, а данные при этом переписываются из массива данных в буфер вытесняемых данных WBB, хранящий адрес, данные и состояние блока до момента записи данных в L2. Кэш L2 выделяет место для размещения вытесняемого блока и присылает запрос, по которому L1 выдает данные и характеризующее их состояние для записи в L2. В случае если после выдачи адреса в L2 и до получения запроса на выдачу данных блока в процессорное ядро приходит снуп-запрос по адресу блока, находящегося в WBB, состояние блока изменяется в WBB по тем же правилам, что и при попадании снуп-запроса в L1D. Это позволяет сохранить когерентность в случае, когда в процессе вытеснения возникают гонки.
6. Кэш-память второго уровня L2
На рис. 4 представлена упрощенная схема организации поддержки когерентности в пределах одного вычислительного узла системы. Кэш-память второго уровня L2 является общей для инструкций и данных и разделяется всеми процессорными ядрами. С точки зрения поддержания когерентности, L2 представляет собой логическую шину, построенную на физической топологии коммутатора. Это позволяет для поддержания когерентности кэшей первого уровня внутри одной СнК использовать наработки по шинным топологиям, полученным из предыдущих поколений микропроцессоров семейства «МЦСТ-R».
Кэш-память второго уровня поддерживает все состояния протокола MOESI. Кэш L2 принимает команды от четырех процессорных ядер и включается во внешний по отношению к данному узлу снупинг. При выполнении любой команды кэш L2 выдает снуп-запрос во все кэш-памяти первого уровня. Одновременно с этим проверяется собственная память тегов. На основании состояния блока в кэшах первого уровня и кэше L2 его контроллер принимает решение о необходимых действиях, которые могут состоять в следующем:

Рис. 4
Поддержка когерентности в пределах узла системы
(L1D – кэш данных первого уровня; L1I – кэш инструкций первого уровня; L1Tag – память тэгов кэша второго уровня; L2 Tag Pipe – кэш-контроллер L2)
В кэш-контроллере L2 реализуется первая из двух точек системной сериализации. Если два запросчика одновременно обращаются в один блок, то запрос, проигравший арбитраж, откладывается до полного выполнения выигравшего запроса. Это решает вопрос гонки между обновлением состояния блока в L1 и следующим снуп-запросом в этот блок.
В случае промаха во все кэш-памяти адрес блока передается в регистры промаха L2 для обращения в оперативную память (выполнение запроса на глобальном уровне). Команда передается в контроллер когерентности, который формирует необходимые снуп-запросы в другие узлы системы. После фиксации результатов каждого из них L2 формирует ответ запросчику и посылает в контроллер когерентности пакет, информирующий о завершении операции. Снуп-ответы могут представлять собой короткий пакет, сообщающий, обнаружен ли данный блок в кэшах соседнего узла, или пакет с данными. Получение данных в качестве снуп-ответа означает, что в другом узле системы были обнаружены модифицированные данные, и ответ из контроллера памяти надо игнорировать, т.к. он не актуален.
Снуп-запросы из других узлов системы поступают в L2 через интерфейс с системным коммутатором и мультиплексируются с запросами процессорных ядер. Коды и семантика снуп-операций в кэше L2 совпадают с таковыми для L1D. При обнаружении данных в состояниях M или O запросчику отсылается пакет с данными блока, иначе запросчику отсылается пакет, подтверждающий выполнение снуп-запроса и содержащий в себе признак наличия данного блока в вычислительном узле системы.
7. Контроллер когерентности
Контроллер когерентности является точкой сериализации второго уровня. При получении команды он проверяет наличие адреса в таблице текущих исполняемых запросов. Если адрес отсутствует, то контроллер заносит его в таблицу и начинает выполнение команды. При получении запроса с адресом, который совпадает с одним из содержащихся в таблице, контроллер когерентности откладывает его выполнение до тех пор, пока не будет получено сообщение о выполнении первого обращения. Это обеспечивает наличие в системе только одного снуп-запроса с данным адресом и исключает гонки между получением запросчиком снуп-ответа на первый запрос и получением следующего снуп-запроса с данным адресом.
При выполнении команды чтения контроллер когерентности одновременно выдает в контроллер памяти адрес и команду чтения и отправляет в системный коммутатор широковещательный снуп-запрос. После получения ответа от контроллера памяти контроллер когерентности немедленно отправляет данные запросчику и ожидает сообщения от него о завершении исполнения команды. После его получения адрес удаляется из таблицы текущих исполняемых запросов.
При исполнении команды записи контроллер когерентности одновременно передает ее совместно с адресом в контроллер памяти и отправляет запросчику пакет, разрешающий передачу записываемых данных. Полученные данные передаются в контроллер памяти. После того, как данные записаны, контроллер памяти сообщает об этом контроллеру когерентности, и тот удаляет адрес из таблицы текущих исполняемых запросов.
Заключение
Систему на кристалле «МЦСТ-R1000» можно считать первым представителем нового поколения серии микросхем ЗАО «МЦСТ», базирующихся на архитектуре SPARC. Ее организация существенно изменена по сравнению с «МЦСТ-R500S». Введены средства поддержки многопроцессорной ccNUMA системы с соединениями «точка-точка», обеспечивающей когерентность всех входящих в нее устройств кэш-памяти, реализована сеть на кристалле, позволяющая создавать любые связные топологии многопроцессорных систем. Впервые в серии реализованы идеи DSM системы с полным отказом от шинной топологии.
Анализ производительности СнК на прототипе, а впоследствии и на опытных образцах, показал, что на большинстве задач она более чем в три раза превышает производительность микросхемы «МЦСТ-R500S», приходящуюся на каждое процессорное ядро, и в пять-шесть раз – суммарную.
Вместе с этим уже сейчас видны пути дальнейшего развития подсистемы памяти систем на кристалле этого ряда «МЦСТ-R»:
Литература
Организация поддержки когерентности в системе на кристалле МЦСТ-R1000На базе СнК могут строиться вычислительные системы, включающие до четырех микросхем «МЦСТ-R1000», совместно содержащих до 36 устройств кэш-памяти. Одной из важнейших задач при построении подобной системы является обеспечение согласованности данных. Описанию ее решения посвящена данная статья.