Следовательно, задержка самого mov должна быть равна 1.
Нет, mov
- это нагрузка. Также нет операции ALU mov
, через которую должны пройти данные.
Таблицы инструкций Агнера Фога не содержат задержки использования нагрузки (как вы измеряете). Они находятся в его микроархиве PDF в таблицах в разделе «Доступ к кешу и памяти» для каждого uarch. например SnB / IvB (раздел 9.13) имеет строку «Уровень 1 данных» с «32 кБ, 8 линий, размер строки 64 В, задержка 4 на ядро».
Эта 4-тактная задержка представляет собой задержку загрузки для цепочки зависимых инструкций, таких как mov rax, [rax]
. Вы измеряете 5 циклов, потому что вы используете режим адресации, отличный от [reg + 0..2047]
. При небольших смещениях единица загрузки предполагает, что использование базового регистра непосредственно в качестве входа для поиска TLB даст тот же результат как результат сумматора. Существует ли штраф, если база + смещение находятся на странице, отличной от базы? . Таким образом, ваш режим адресации [disp32 + rax]
использует обычный путь, ожидая еще один цикл для результата сумматора, прежде чем начать поиск TLB в порту загрузки.
Для большинства операций между разными доменами (например, целочисленные регистры и регистры XMM) вы действительно можете измерить только двустороннюю передачу, например movd xmm0,eax
/ mov eax, xmm0
, и трудно выделить это отдельно и выяснить, какова задержка каждая инструкция отдельно 1 .
Для нагрузок вы можете подключиться к другой загрузке, чтобы измерить задержку загрузки кеша вместо цепочки хранения / перезагрузки.
Агнер по какой-то причине решил только посмотреть на задержку пересылки магазина для своих таблиц и сделать совершенно произвольный выбор, как разделить задержку пересылки магазина между магазином и перезагрузка.
(из листа «определения терминов» его таблицы инструкций, слева от Введения)
Невозможно измерить задержку чтения или записи памяти
инструкция с программными методами. Можно только измерить
комбинированная задержка записи в память, за которой следует чтение из
тот же адрес. Здесь измеряется не доступ к кешу
время, , потому что в большинстве случаев микропроцессор достаточно умен, чтобы
«перенаправление магазина» непосредственно из блока записи в блок чтения
вместо того, чтобы ждать, пока данные перейдут в кеш и вернутся снова.
Задержка этого процесса пересылки хранилища делится произвольно
в латентность записи и латентность чтения в таблицах . Но по факту,
единственное значение, которое имеет смысл для оптимизации производительности, это сумма
времени записи и чтения.
Это, очевидно, неверно: задержка использования нагрузки L1d предназначена для погони за указателями через уровни косвенности. Вы можете утверждать, что это просто переменная, потому что некоторые загрузки могут отсутствовать в кеше, но если вы собираетесь выбрать что-то, чтобы поместить в таблицу, вы могли бы также выбрать задержку использования нагрузки L1d. А затем вычислите значения задержки магазина так, чтобы store + латентность загрузки = латентность пересылки хранилища, как сейчас. В этом случае Intel Atom будет иметь задержку хранилища = -2, потому что он имеет задержку 3c L1d при загрузке , но переадресацию хранилища 1c в соответствии с руководством Агнера по uarch.
Это не так просто для загрузки, например, в регистры XMM или YMM, но все же возможно, когда вы определите задержку movq rax, xmm0
. Для регистров x87 сложнее, потому что нет способа напрямую получить данные из st0
в eax
/ rax
через ALU, вместо сохранения / перезагрузки. Но, возможно, вы могли бы сделать что-то с сравнением FP, например, fucomi
, который устанавливает целочисленные флаги напрямую (на процессорах, которые его имеют: P6 и выше).
Тем не менее, было бы намного лучше, если бы хотя бы целочисленная задержка загрузки отражала задержку отслеживания указателя. IDK, если кто-то предложил обновить таблицы Агнера для него, или если он примет такое обновление. Тем не менее, на большинстве uarches потребуется новое тестирование, чтобы убедиться в правильной задержке загрузки для разных наборов регистров.
сноска 1: Например, http://instlatx64.atw.hu не пытается, а просто говорит «набор регистраций изменений» в столбце задержки, а полезные данные - только в столбце пропускной способности. Но у них есть строки для MOVD r64, xmm+MOVD xmm, r64
туда-обратно, в этом случае 2 цикла на IvB, поэтому мы можем быть достаточно уверены, что они только 1с в одну сторону. Не ноль в одну сторону. : P
Но для загрузок в целочисленные регистры они показывают 4-тактовую задержку использования нагрузки IvB для MOV r32, [m32]
, потому что, очевидно, они тестируют с [reg + 0..2047]
режимом адресации.
Другие источники информации о задержке кэша:
https://www.7 -cpu.com / содержит хорошие детали для множества других уарчей, даже для многих не x86, таких как ARM, MIPS, PowerPC и IA-64.
На страницах есть другие подробности, такие как размер кэша и TLB, время TLB, результаты эксперимента по пропуску ветвления и пропускная способность памяти. Детали задержки кэша выглядят так:
( со страницы Skylake )
- L1 Data Cache Latency = 4 цикла для простого доступа через указатель
- L1 Data Cache Latency = 5 циклов для доступа со сложным вычислением адреса (
size_t n, *p; n = p[n]
).
- Задержка кэша L2 = 12 циклов
- Задержка кэша L3 = 42 такта (ядро 0) (i7-6700 Skylake 4,0 ГГц)
- Задержка кэша L3 = 38 циклов (i7-7700K 4 ГГц, Kaby Lake)
- Задержка ОЗУ = 42 такта + 51 нс (i7-6700 Skylake)