- •7. Система памяти
- •7.1. Базовые концепции
- •7.2. Быстродействие, объем и стоимость
- •7.3.1. Функция отображения
- •7.3.2. Алгоритмы замещения
- •7.3.3. Примеры технологий отображения
- •7.3.4. Организация кэша в коммерческих процессорах
- •7.4. Производительность
- •7.4.1. Чередование операций
- •7.4.2. Частота попаданий и накладные расходы при промахах
- •7.4.3. Кэши на микросхеме процессора
- •7.4.4. Другие способы увеличения быстродействия
- •7.5. Виртуальная память
- •7.5.1. Преобразование адресов
- •7.6. Требования к управлению памятью
7.4.4. Другие способы увеличения быстродействия
Кроме уже рассмотренных нами ключевых конструкторских решений существует еще несколько возможностей повышения производительности системы памяти. О трех из них рассказывается в настоящем разделе.
Буферизация записи
При использовании протокола сквозной записи каждой операции записи соответствует операция сохранения нового значения в основной памяти. Если процессор будет ждать окончания этой операции, его работа очень сильно замедлится. Однако дальнейшая работа процессора в ближайшее время, как правило, не зависит от результата операции записи, так что ему незачем дожидаться ее завершения. А раз так, в систему памяти можно добавить буфер записи, предназначенный для временного хранения результатов операций записи. Процессор должен поместить в него запрос на запись и продолжать свою работу. А тем временем, уже без его участия, запрос будет отослан в основную память, когда та не будет занята выполнением запросов на чтение. Запросы на чтение должны обслуживаться немедленно, поскольку процессор обычно не может продолжать работу без тех данных, которые он запросил. Поэтому у запросов на чтение более высокий приоритет, чем у запросов на запись.
В буфере записи может скопиться много запросов. Поэтому не исключены ситуации, когда запросы на чтение ссылаются на данные, которые еще находятся в буфере записи. Для обеспечения корректной работы системы адреса данных, подлежащих чтению из памяти, обязательно сравниваются с адресами в буфере записи, и в случае их совпадения используются данные из буфера записи.
При использовании протокола обратной записи ситуация становится несколько иной. В этом случае в результате операции записи изменяются только данные в кэше. Но что происходит, когда по причине промаха нужно прочитать в кэш новый блок данных, поместив его на место блока с измененными и еще не сохраненными данными? Перед удалением из кэша измененный блок, конечно же, записывается в основную память. Если обратная запись производится часто, процессору приходится подолгу дожидаться выполнения операции чтения из памяти очередного блока данных. Поэтому разумнее сначала прочитать новый блок, чтобы процессор мог продолжить работу, а потом заняться записью в память удаленного из кэша блока. Для этого нужен быстрый буфер записи, куда перед чтением нового блока будет временно помещаться старый. Когда новый блок будет прочитан из основной памяти, в нее можно будет записать содержимое старого блока. Как видите, буфер записи необходим при любом из протоколов записи.
Упреждающая выборка
Рассказывая о технологиях кэширования, мы предполагали, что данные копируются в кэш тогда, когда они нужны процессору. Это означает, что процессор обращается к памяти, и если в кэше не оказывается нужных данных, таковые загружаются из основной памяти. Однако в этом случае процессору приходится ждать поступления новых данных (накладные расходы промаха), что, конечно же, замедляет его работу.
Чтобы процессор не простаивал, необходимые данные следует помещать в кэш еще до того, как они потребуются. Проще всего это сделать программным путем, для чего в системе команд процессора должна быть предусмотрена команда упреждающей выборки. Ее выполнение приводит к загрузке в кэш указанных в ней данных, как в случае промаха. Однако процессор не ждет адресованных данных. Команда упреждающей выборки вставляется в программу для того, чтобы данные были загружены в кэш до того, как они потребуются программе. Предполагается, что выборка производится, пока процессор занят выполнением других команд, не вызывающих промахов чтения, так что доступ к основной памяти осуществляется параллельно с процессом вычислений.
Команды упреждающей выборки могут быть вставлены в программу как программистом, так и компилятором. Конечно, лучше возложить эту задачу на компилятор, тем более что справляется он с такой задачей вполне успешно. С использованием команд упреждающей выборки связаны и некоторые издержки, поскольку эти команды увеличивают длину программы. Более того, некоторые из них могут загружать в кэш данные, не используемые последующими командами. Так может произойти в том случае, если заранее помещенные в кэш данные будут вытеснены другими данными еще до того, как программа успеет к ним обратиться. Однако в целом программная упреждающая выборка положительно сказывается на производительности, и многие процессоры поддерживают эту функцию.
Упреждающая выборка может выполняться и аппаратным путем, но для этого необходимы дополнительные схемы, определяющие последовательность обращений к памяти и прогнозирующие следующие обращения. Существует множество стратегий и соответствующих им схем прогнозирования, но их анализ выходит за рамки нашего издания.
Процессор Intel Pentium 4 поддерживает и программную и аппаратную упреждающую выборку. У него имеются специальные команды, копирующие блок данных в кэш заданного уровня. Средства аппаратной упреждающей выборки копируют данные в кэш второго уровня, используя специальный алгоритм, который позволяет определить, насколько интенсивно они использовались прежде.
Кэш без блокировок
Если команды упреждающей выборки постоянно прерывают нормальное выполнение программы, целесообразность их применения оказывается под большим сомнением. Так бывает, если упреждающая выборка мешает обращениям к кэшу. Получается, что на то время, пока выполняется выборка данных, кэш заблокирован для процессора. Для решения этой проблемы архитектуру кэша можно модифицировать таким образом, чтобы процессор мог обращаться к кэшу параллельно с выборкой из памяти новых данных. Более того, желательно, чтобы кэш поддерживал несколько параллельных операций выборки.
Кэш, в котором обработка промахов и команд упреждающей выборки может откладываться, с тем чтобы процессор мог обратиться к имеющимся в нем данным, называется кэшем без блокировок (lockup-free). Поскольку кэш способен обработать за раз лишь один промах, в него должна быть включена схема для отслеживания остальных промахов, ожидающих очереди на обработку. Для этого нужны специальные регистры, в которых хранилась бы информация об отложенных промахах. Кэши без блокировок впервые появились в 1980-х годах, в компьютерах серии Cyber, производившихся компанией Control Data.
Программная упреждающая выборка производится с целью предотвратить блокировку кэша в случае промахов при выполнении операции чтения. Но существует еще одно, более важное обстоятельство. Как вы понимаете, в процессорах с конвейерной организацией, при которой параллельно выполняются несколько команд, промах чтения одной команды может задержать выполнение остальных. Кэш без блокировок сокращает вероятность таких задержек. Мы еще вернемся к этому вопросу в разделе 7, когда будем обсуждать конвейерное выполнение команд.