Начнем с простого: представим, что у нас есть микропроцессор, и адрес памяти кодируется битами. Это означает, что в нашей оперативной памяти адресация происходит от
до
. Основная идея заключается в делении оперативной памяти на ячейки (
) одинакового размера (
). То есть количество таких ячеек равно
. Будем их нумеровать от
до
. Таким образом, зная количество битов адреса
и размер блока
, мы можем пронумеровать блоки оперативной памяти. Заметим, что оптимальным размером
была бы степень двойки (по очевидным причинам). Так в современных процессорах и происходит, поэтому далее считаем
Зачем же нужен кэш?
Итак, у нас есть адрес памяти с битами. Очевидно, мы хотим узнать, какому блоку в оперативной памяти соответствует данный адрес. Для этого вводится промежуточная память между процессором и оперативной памятью, которая называется кэшом. Доступ к кэшу на порядок быстрее, чем к оперативной памяти, но размер его также существенно меньше оперативной памяти. В кэше память также разбита на ячейки(
) с таким же размером, как и у оперативной памяти, то есть размер ячейки равен
. Только, естественно, количество
-ов будет на порядок меньше, чем в оперативной памяти. Их количество равно
, поэтому также размер кэша обычно является степенью двойки. Пусть далее
. Нумеруются блоки в кэше также начиная с нуля.
Теперь покажем, как же связываются блоки кэша с блоками оперативной памяти. Все очень просто: берем -ой блок из
и связываем с
-ым блоком из кэша, затем
-ый из
с
-ым и так далее до
. Затем
-ый из
связывается опять с
-ым блоком кэша и так далее. Ничего не заметили? Номер ячейки кэша определяется простым взятием по модулю
. То есть мы научились связывать ячейки оперативки с ячейками кэша, при этом заметьте, одной ячейке кэша соответствует несколько ячеек оперативной памяти.
Теперь мы все знаем, чтобы понять, как же работает определение нужной ячейки памяти по адресу:
1. Берем бит адреса и отбрасываем
последних бит(эти
бит называются offset-ом).
2. Берем последних бит из оставшегося набора. Эти
бит как раз однозначно определяют номер блока в кэше, где мы будем пытаться найти нужную ячейку памяти адреса.
3. Оставшиеся бит называются
-ом. И вот с помощью него мы можем теперь однозначно идентифицировать нужную ячейку памяти из всех ячеек, соответствующих блоку кэша.
Именно поэтому в одной «строчке» кэша хранится номер блока и
уже загруженной страницы в кэш, соответствующей данному блоку. Это сделано для снижения затрат на обращение в оперативную память.
Подводя глобальные итоги, давайте еще раз закрепим полученные знания:
У нас есть адрес, состоящий из бит, и мы хотим определить ячейку памяти, соответствующую данному адресу:
Шаг 1. Отбрасываем последние бит (offset)
Шаг 2. Берем последние бит; определили номер блока кэша
Шаг 3. Оставшиеся бит определяют
, по которому мы находим в блоке кэша с номером, определенном в Шаге 2, нужную ячейку памяти.
Все довольно просто, скоро добавлю картинки, и это, надеюсь, внесет еще больше ясности 🙂