Кэш-память

 

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

Как мы уже отмечали, есть два пути решения проблемы. Самый простой из них — начать считывать информацию из памяти и при этом продолжать выпол­нение команд, но если какая-либо команда попытается использовать слово до того, как оно считано из памяти, процессор должен приостановить работу. Чем мед­леннее работает память, тем чаще будет возникать такая ситуация и тем больше окажется время простоя процессора. Например, если отсрочка составляет 10 цик­лов, весьма вероятно, что одна из 10 следующих команд попытается использо­вать слово, которое еще не считано из памяти.

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

На самом деле эта проблема не технологическая, а экономическая. Инженеры знают, как создать память, которая работает так же быстро, как процессор. Одна­ко ее приходится помещать прямо на микросхему процессора (поскольку инфор­мация через шину поступает очень медленно). Размещение памяти большого объема на микросхеме процессора делает его больше и, следовательно, дороже, и даже если бы стоимость не имела значения, все равно существуют ограничения на размеры создаваемых процессоров. Таким образом, приходится выбирать между быстрой памятью небольшого объема и медленной памятью большого объема. (Мы, естественно, предпочли бы иметь быструю память большого объе­ма и к тому же дешевую.)

Интересно отметить, что существуют технологии, объединяющие небольшую и быструю память с большой и медленной, что позволяет по разумной цене по­лучить память и с высокой скоростью работы, и большой емкости. Память не­большого объема с высокой скоростью работы называется кэш-памятью (от французского слова «сасЬег» — «прятать»1; читается «кашэ»). Далее мы кратко опишем, как используется кэш-память и как она работает. Более подробное опи­сание вы найдете в главе 4.

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

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

1 В английском языке слово «cash» получило значение «наличные (карманные) деньги», то есть то, что под рукой. А уже из него и образовался термин «кэш», который относят к сверхоперативной па­мяти. — Примем, научн. ред.

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

Ситуация, когда при последовательных обращениях к памяти в течение неко­торого промежутка времени используется только небольшая ее область, назы­вается принципом локальности. Этот принцип составляет основу всех систем кэш-памяти. Идея состоит в том, что когда определенное слово вызывается из памяти, оно вместе с соседними словами переносится в кэш-память, что позво­ляет при очередном запросе быстро обращаться к следующим словам. Общее устройство процессора, кэш-памяти и основной памяти иллюстрирует рис. 2.13. Если слово считывается или записывается k раз, компьютеру требуется сделать 1 обращение к медленной основной памяти и k - 1 обращений к быстрой кэш-па­мяти. Чем больше тем выше общая производительность.

clip_image002

Шина

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

Мы можем сделать и более строгие вычисления. Пусть с — время доступа к кэш-памяти, т — время доступа к основной памяти и h — коэффициент кэш-по­паданий (hit ratio), который показывает соотношение числа обращений к кэш памяти и общего числа всех обращений к памяти. В нашем примере h = (k - l)/k. Некоторые авторы выделяют коэффициент кэш-промахов (miss ratio), равный 1 -h.

Таким образом, мы можем вычислить среднее время доступа: Среднее время доступа = с + (1 - К) т.

Если h —> 1, то есть все обращения делаются только к кэш-памяти, то время доступа стремится к с. С другой стороны, если h —» 0, то есть каждый раз нужно обращаться к основной памяти, то время доступа стремится кс + ш: сначала тре­буется время с для проверки кэш-памяти (в данном случае безуспешной), а за­тем — время т для обращения к основной памяти. В некоторых системах обра­щение к основной памяти может начинаться параллельно с исследованием кэш-памяти, чтобы в случае кэш-промаха цикл обращения к основной памяти уже начался. Однако эта стратегия требует способности останавливать процесс обращения к основной памяти в случае кэш-попадания, что усложняет разработ­ку подобного компьютера.

Основная память и кэш-память делятся на блоки фиксированного размера с учетом принципа локальности. Блоки внутри кэш-памяти обычно называют строками кэша (cache lines). При кэш-промахе из основной памяти в кэш-па­мять загружается вся строка, а не только необходимое слово. Например, если строка состоит из 64 байт, обращение к адресу 260 влечет за собой загрузку в кэш-память всей строки (байты с 256 по 319) на случай, если через некоторое время понадобятся другие слова из этой строки. Такой путь обращения к памяти более эффективен, чем вызов каждого слова по отдельности, потому что одно кратный вызов k слов происходит гораздо быстрее, чем вызов одного слова k раз.

Кэш-память очень важна для высокопроизводительных процессоров. Однако здесь возникает ряд вопросов. Первый вопрос — объем кэш-памяти. Чем больше объем, тем лучше работает память, но тем дороже она стоит. Второй вопрос — размер строки кэша. Кэш-память объемом 16 Кбайт можно разделить на 1024 строки по 16 байт, 2048 строк по 8 байт и т. д. Третий вопрос — механизм орга­низации кэш-памяти, то есть то, как она определяет, какие именно слова нахо­дятся в ней в данный момент. Устройство кэш-памяти мы рассмотрим подробно в главе 4.

Четвертый вопрос — должны ли команды и данные находиться вместе в об­щей кэш-памяти. Проще всего разработать объединенную кэш-память (unified cache), в которой будут храниться и данные и команды. В этом случае вызов ко­манд и данных автоматически уравновешивается. Однако в настоящее время существует тенденция к использованию разделенной кэш-памяти (split cache), когда команды хранятся в одной кэш-памяти, а данные — в другой. Такая архи­тектура также называется гарвардской (Harvard architecture), поскольку идея использования отдельной памяти для команд и отдельной памяти для данных впервые воплотилась в компьютере Marc III, который был создан Говардом Айкеном (Howard Aiken) в Гарварде. Современные разработчики пошли по это му пути, поскольку сейчас широко распространены конвейерные архитектуры, а при конвейерной организации должна быть возможность одновременного дос­тупа и к командам, и к данным (операндам). Разделенная кэш-память позволяет осуществлять параллельный доступ, а общая — нет. К тому же, поскольку коман­ды обычно не меняются во время выполнения программы, содержание кэша ко­манд не приходится записывать обратно в основную память.

Наконец, пятый вопрос — количество блоков кэш-памяти. В настоящее время очень часто кэш-память первого уровня располагается прямо на микросхеме процессора, кэш-память второго уровня — не на самой микросхеме, но в корпусе процессора, а кэш-память третьего уровня — еще дальше от процессора.

Источник: Таненбаум Э. Архитектура компьютера. 5-е изд. (+CD). — СПб.: Питер, 2007. — 844 с: ил.

Предлагаю ознакомиться с аналогичными статьями: