Direct Cache

Начнем с простого: представим, что у нас есть микропроцессор, и адрес памяти кодируется \bf{d} битами. Это означает, что в нашей оперативной памяти адресация происходит от \bf{0} до \bf{2^d-1} . Основная идея заключается в делении оперативной памяти на ячейки (\bf{Blocks}) одинакового размера (\bf{BlockSize}). То есть количество таких ячеек равно \bf{\frac{2^d}{BlockSize}} . Будем их нумеровать от \bf{0} до \bf{\frac{2^d}{BlockSize}-1}. Таким образом, зная количество битов адреса \bf{d} и размер блока \bf{BlockSize}, мы можем пронумеровать блоки оперативной памяти. Заметим, что оптимальным размером \bf{BlockSize} была бы степень двойки (по очевидным причинам). Так в современных процессорах и происходит, поэтому далее считаем \bf{BlockSize = 2^b.}

Зачем же нужен кэш?

Итак, у нас есть адрес памяти с \bf{d} битами. Очевидно, мы хотим узнать, какому блоку в оперативной памяти соответствует данный адрес. Для этого вводится промежуточная память между процессором и оперативной памятью, которая называется кэшом. Доступ к кэшу на порядок быстрее, чем к оперативной памяти, но размер его также существенно меньше оперативной памяти. В кэше память также разбита на ячейки(\bf{Blocks}) с таким же размером, как и у оперативной памяти, то есть размер ячейки равен \bf{BlockSize}. Только, естественно, количество \bf{block}-ов будет на порядок меньше, чем в оперативной памяти. Их количество равно \bf{cacheBlocksNum = \frac{CacheSize}{BlockSize}}, поэтому также размер кэша обычно является степенью двойки. Пусть далее \bf{CacheSize = 2^c}. Нумеруются блоки в кэше также начиная с нуля.

Теперь покажем, как же связываются блоки кэша с блоками оперативной памяти. Все очень просто: берем \bf{0}-ой блок из \bf{RAM} и связываем с \bf{0}-ым блоком из кэша, затем \bf{1}-ый из \bf{RAM} с \bf{1}-ым и так далее до \bf{cacheBlocksNum-1}. Затем  \bf{cacheBlocksNum}-ый из \bf{RAM} связывается опять с \bf{0}-ым блоком кэша и так далее. Ничего не заметили? Номер ячейки кэша определяется простым взятием по модулю  \bf{cacheBlocksNum}. То есть мы научились связывать ячейки оперативки с ячейками кэша, при этом заметьте, одной ячейке кэша соответствует несколько ячеек оперативной памяти.

Теперь мы все знаем, чтобы понять, как же работает определение нужной ячейки памяти по адресу:

1. Берем \bf{d} бит адреса и отбрасываем \bf{b} последних бит(эти \bf{b} бит называются offset-ом).

2. Берем \bf{c} последних бит из оставшегося набора. Эти \bf{c} бит как раз однозначно определяют номер блока в кэше, где мы будем пытаться найти нужную ячейку памяти адреса.

3. Оставшиеся \bf{d-b-c} бит называются \bf{tag}-ом. И вот с помощью него мы можем теперь однозначно идентифицировать нужную ячейку памяти из всех ячеек, соответствующих блоку кэша.

Именно поэтому в одной «строчке» кэша хранится номер блока \bf{blockNumber} и \bf{TAG} уже загруженной страницы в кэш, соответствующей данному блоку. Это сделано для снижения затрат на обращение в оперативную память.

Подводя глобальные итоги, давайте еще раз закрепим полученные знания:

У нас есть адрес, состоящий из \bf{d} бит, и мы хотим определить ячейку памяти, соответствующую данному адресу:

Шаг 1. Отбрасываем последние \bf{b} бит (offset)

Шаг 2. Берем последние \bf{c} бит; определили номер блока кэша

Шаг 3. Оставшиеся \bf{d-b-c} бит определяют \bf{tag}, по которому мы находим в блоке кэша с номером, определенном в Шаге 2, нужную ячейку памяти.

Все довольно просто, скоро добавлю картинки, и это, надеюсь, внесет еще больше ясности 🙂

 

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google photo

Для комментария используется ваша учётная запись Google. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s