logo
Методичка

3.3 Протоколы когерентности памяти микропроцессоров

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

Протокол когерентности MESI

В микропроцессорах, предусматривающих возможность их использования в мультипроцессорных системах с архитектурой SMP, применяется протокол MESI (Modified Exclusive Shared Invalid) организации кэш-памяти с обратной записью, который предотвращает лишние передачи данных между кэш-памятью и основной памятью. Так, если данные в кэш-памяти не изменялись, то незачем их пересылать.

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

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

Каждая строка кэш-памяти микропроцессора может находиться в одном из следующих состояний:

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

Для управления режимом работы механизма поддержки когерентности используется бит WT, состояние 1 которого задает режим сквозной (write-through) записи, а состояние 0 - режим обратной (write-back) записи в кэш-память.

При исполнении команд чтения и записи состояние строки кэш-памяти, к которой выполняется доступ, определяется в таблице 3.1.

Таблица 3.1. Переходы между состояниями в протоколе MESI при выполнении команд чтения и записи

Исходное состояние строки

Состояние после чтения

Состояние после записи

I

Если WT = 1 тогда Е, иначе S.

Сквозная запись в основную память; I

S

S

Сквозная запись в основную память; если WT= 1 тогда Е, иначе S.

E

E

M

M

M

M

Промах чтения в кэш-памяти заставляет вызвать строку из основной памяти и сопоставить ей состояние Е или S. Кэш-память заполняется только при промахах чтения. При промахе записи транзакция записи помещается в буфер и посылается в основную память при предоставлении шины.

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

При состоянии I строки команда записи в эту строку изменяет только содержимое строки основной памяти (сквозная запись), но не изменяет содержимое кэш-памяти и сохраняет состояние строки I.

В состоянии S строки чтение данных из этой строки не меняет ее состояние. Если установлен режим сквозной записи, то после завершения записи состояние строки меняется на Е, при режиме обратной записи выполняется сквозная запись, но состояние строки остается прежним – S.

Если состояние строки Е, то при команде чтения это состояние сохраняется, а выполнение команды "запись" переводит строку в состояние М.

Наконец, если состояние строки М, то, как команды чтения, так и команды записи не меняют состояния строки.

Для поддержки когерентности строк кэш-памяти при операциях ввода/вывода и обращениях в основную память других процессоров на шине генерируются специальные циклы опроса состояния типов кэш-памяти. Эти циклы опрашивают типы кэш-памяти на предмет хранения в них строки, которой принадлежит адрес, используемый в операции, инициировавшей циклы опроса состояния. Возможен режим принудительного перевода строки в состояние I, который задается сигналом INV. При этом состояние строк определяется в таблице 3.2.

Таблица 3.2. Переходы между состояниями в протоколе MESI при операциях ввода/вывода

Исходное состояние

INV=0

INV=1

I

I

I

S

S

I

E

S

I

M

S, обратная запись строки

I, обратная запись строки

Протокол DASH

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

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

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

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

Каждый модуль памяти имеет для каждой строки, резидентной в модуле, список модулей, в кэш-памяти которых размещены копии этой кэш-строки.

С каждой строкой в резидентном для нее модуле связаны три ее возможных глобальных состояния:

Кроме этого, каждая кэш-строка находится в одном из трех локальных состояний:

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

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

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

Если процессор выполняет операцию записи и состояние кэш-строки, в которую производится запись "измененная", то запись выполняется, и вычисления продолжаются. Если состояние кэш-строки "невозможная к использованию" или "разделяемая", то модуль посылает в резидентный для кэш-строки модуль запрос на захват в исключительное использование этой кэш-строки и приостанавливает выполнение записи до получения подтверждений, что все остальные модули, разделяющие с ним рассматриваемую кэш-строку, перевели ее копии в состояние "невозможная к использованию".

Если глобальное состояние кэш-строки в резидентном модуле "некэшированная", то кэш-строка отсылается запросившему модулю, и этот модуль продолжает приостановленные вычисления.

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

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

Подход к выбору протоколов когерентности

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

Организация кэш-памяти микропроцессоров

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