Иллюстрация того, как адреса памяти используются ЦП - PullRequest
0 голосов
/ 14 июля 2020

Дано: все байты для чтения находятся в ближайшем кэше ЦП (т.е. доступны как можно скорее); архитектура x86; это актуально только тогда, когда я использую обозначение битов / байтов z / y ../ X, как именно используются биты / байты архитектуры (например, варианты архитектуры x86-64 и 32-разрядные версии).

CPU запрашивает байт из кеша, обращаясь к нему с помощью своего тега блока, за которым естественно (или которому предшествует) смещение блока (для доступа к отдельному байту с использованием комбинированного КЛЮЧА из отправленного в кеш, предполагая, что запрошенный блок кеша доступен, а не холоден). Загружает ли ЦП указанный байт и следующие байты 3/7 ... / X (в зависимости от архитектуры) после него? Предполагая, что это так, и предполагая, что это минимум, который ЦП может читать из памяти за раз, позвольте назвать это МИНИМАЛЬНОЕ КОЛИЧЕСТВО ЧИТАЕМЫХ БАЙТОВ ПАМЯТИ (пожалуйста, поправьте меня, если я ошибаюсь в точном термине). Поэтому я спрашиваю: должно ли смещение блока быть максимумом (РАЗМЕР БЛОКА - 1 - МИНИМАЛЬНОЕ КОЛИЧЕСТВО ЧИТАЕМЫХ БАЙТОВ ПАМЯТИ)? Я также спрашиваю: может ли ЦП начать чтение с адреса смещения блока, который не кратен МИНИМАЛЬНОМУ КОЛИЧЕСТВУ ЧИТАЕМЫХ БАЙТОВ ПАМЯТИ?

Чтобы ответить на вопросы ниже, сначала ответьте на то, что указано выше. Рассмотрим специально следующий вопрос: «Загружает ли ЦП указанный байт и следующие 3/7 ... / X байтов (в зависимости от архитектуры) после него?».

Если моя гипотеза не верна, не это означает, что ЦП может читать любой отдельный байт сам по себе и просто копировать его содержимое в младшие биты 32/64 ... / X битного регистра (или биты помещаются в больший регистр каким-то другим способом?)? Есть ли для этой цели регистры меньшего размера?

Ответы [ 2 ]

2 голосов
/ 15 июля 2020

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

Кэш обычно встроен в шину процессора, так что кеш может обрабатывать запрос или передавать его, либо выполнять выборку или вытеснение строки кэша и т. Д. c. Ширина и глубина sram (s) в кэше, и, как следствие, теги и тому подобное, которые являются частью этого дизайна кеша, и, естественно, должны быть спроектированы так, чтобы соответствовать остальной части системы. но процессору не нужно заботиться, он отправляет выборку, чтение или запись туда, в зависимости от дизайна это может указывать на кэшируемость или, что более вероятно, это mmu, который находится между процессором и кешем, и пользователь использует mmu для указать кэшируемость, а также виртуальные адреса и т. д. дизайн кеша использует тег / статус, чтобы определить, есть ли совпадение или промах, затем дизайн определяет, что делать дальше. Каков размер строки кэша, который определяет запрос на шине на дальней стороне кеша. При необходимости, если есть промах, но нет места для этого, тогда должно произойти выселение, и то, что будет выселено, зависит от конструкции, а иногда и от программируемости кеша.

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

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

Итак, если бы у вас было 128 строка битового кэша в кэше L1, с 32-битной шиной процессора и 32-битным sram в кэше, и хотел выполнить 8-битное чтение, тогда в конечном итоге 32 бита, содержащие этот байт в sram кэша, будут прочитаны и помещены шина для процессора, который затем извлекает байт из шины. Это нетипично, но, естественно, можно спроектировать любой процессор / микросхему, и при желании это может быть недостаточно или чрезмерно усложнено. read, байт изменен и записан обратно вместе с указанием, что строка грязная.

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

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

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

Запросы и адрес процессора, MMU, уровни кешей и медленная загрузка на дальнем конце могут быть затронуты. спецификация / дизайн инструкции определяет размер передачи, которая выходит из процессора и кэшируется или нет. И каждый уровень просто выполняет свою работу.

Некоторые конструкции процессоров / систем таковы, что вы должны выполнять согласованную передачу, x86 по разным причинам не требует этого, но mips / arm делают / делают. x86 эволюционировал, чтобы содержать много накладных расходов, где mips и arm обеспечивают более высокую производительность. Его линия длиной в милю с множеством коробок против линейки спортивных автомобилей, по одной коробке в каждой. Принудительное выравнивание является частью этой работы. x86 разрешает операции различного размера по любому (байтовому) адресу. рука в наши дни тоже работает, но вы можете пострадать от снижения производительности (это как поезд, сбивающий маленькое животное, а не спортивный автомобиль), поэтому это нежелательно. И принудительное выравнивание обычно программируется, вы можете установить, разрешить это или нет.

Итак, минимальное количество байтов на большинстве процессоров составляет 8, кроме того, это зависит от набора команд 16? 32? 64? 128? и так далее. И это не значит, что, поскольку вы выполняете 128-битную запись, это означает, что одна передача по шине будет обрабатывать ее. Если у вас 64-битная шина, и вы выполняете 128-битную передачу, выровненную по 32-битной границе, скажем, 0x10004, но не по 64-битной границе, которая может превратиться в три передачи в зависимости от процессора / шины 32-битная по 0x10004, 64-битная по адресу 0x10010 и 32 бита по адресу 0x10014. Или он может выполнить 128-битную передачу (8 байтов) по невыровненному адресу 0x10004, и кэш или периферийное устройство на другой стороне шины должны иметь дело с этим.

x86, конечно, имеет ситуацию, когда у вас есть один регистр, к которому можно получить доступ по частям al, ah, ax, eax, rax, и в результате то, что делает один байт из шины, зависит для этого процессора от инструкции, а документация / дизайн этой инструкции указывает, что происходит (mov al, byte ptr [rbx] влияет только на 8 бит rax). Это не типично, либо набор инструкций напрямую, либо пользователь должен добавить дополнительный код для обработки регистров, поэтому, если вы хотите изменить только один байт в регистре в зависимости от набора инструкций, нередко потребуется использовать второй регистр для выполнения чтения, затем, возможно, третий регистр для маскировки регистра назначения (и второго регистра, если необходимо), если необходимо, сдвиньте второй регистр, а затем переместите биты в регистр назначения.

ldrb r1,[r3]
ldr r2,=0xFFFF00FF
and r0,r0,r2
lsl r1,r1,#8
orr r0,r0,r1

люди, которые собираются сказать вам, что при использовании меньшего al, ah et c производительность падает, в зависимости от чипа и микрокодирования (x86 микрокодируется, как и многие CISC), поэтому, хотя ris c выглядит ужасно это не означает, что cis c не является внутренним.

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

1 голос
/ 14 июля 2020

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

https://softwareengineering.stackexchange.com/questions/363370/how-does-a-cpu-load-multiple-bytes-at-once-if-memory-is-byte-addressed

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...