У mov r64, m64 задержка в один или два цикла?

Я использую IvyBridge, я написал следующую простую программу для измерения задержки mov:

section .bss
align   64
buf:    resb    64

section .text
global _start
_start:
    mov rcx,    1000000000
    xor rax,    rax
loop:
    mov rax,    [buf+rax]

    dec rcx,
    jne loop

    xor rdi,    rdi
    mov rax,    60
    syscall

perf показывает результат:

 5,181,691,439      cycles

Таким образом, каждая итерация имеет задержку в 5 циклов. Я искал из нескольких онлайн-ресурсов, задержка кеша L1 равна 4. Следовательно, задержка самого mov должна быть равна 1.

Однако таблица инструкций Агнера показывает, что mov r64, m64 имеет задержку в 2 цикла для IveBridge. Я не знаю другого места, где можно найти эту задержку.

Я ошибаюсь в указанной выше программе измерения? Почему эта программа показывает, что задержка mov равна 1, а не 2?

(Я получил тот же результат, используя кэш L2: если buf+rax - это L1, не попавший в L2, аналогичные измерения показывают, что mov rax, [buf+rax] имеет задержку в 12 циклов. IvyBridge имеет задержку в 11 циклов кеш-памяти L2, поэтому задержка mov по-прежнему составляет 1 цикл)


person user10865622    schedule 07.01.2019    source источник


Ответы (1)


Следовательно, задержка самого mov должна быть 1.

Нет, mov - это нагрузка. Также нет операции ALU mov, через которую должны проходить данные.


Таблицы инструкций Агнера Фога не содержат информацию о задержке использования нагрузки (как вы измеряете). Они находятся в его PDF-файле microarch в таблицах в разделе кеша и доступа к памяти для каждого uarch. например SnB / IvB (раздел 9.13) имеет строку данных уровня 1 с 32 кБ, 8-полосным размером строки 64 B, задержкой 4 на каждое ядро.

Эта задержка в 4 цикла - это задержка использования нагрузки для цепочки зависимых инструкций, таких как mov rax, [rax]. Вы измеряете 5 циклов, потому что используете режим адресации, отличный от [reg + 0..2047]. При небольших смещениях блок нагрузки предполагает, что использование базового регистра непосредственно в качестве входных данных для поиска TLB даст тот же результат как используя результат сумматора. Есть ли штраф когда base + offset находится на другой странице, чем base?. Таким образом, ваш режим адресации [disp32 + rax] использует обычный путь, ожидая еще один цикл для результата сумматора перед запуском поиска TLB в порту загрузки.


Для большинства операций между разными доменами (например, целочисленные регистры и регистры XMM) вы действительно можете измерить только круговой обход, такой как movd xmm0,eax / mov eax, xmm0, и трудно выделить это отдельно и выяснить, какова задержка каждой инструкции по отдельности 1.

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

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

(из определения терминов в его электронной таблице с инструкциями, слева после введения)

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

Это явно неверно: задержка при загрузке L1d - это вещь для поиска указателя через уровни косвенного обращения. Вы можете утверждать, что это просто переменная, потому что некоторые нагрузки могут отсутствовать в кеше, но если вы собираетесь выбрать что-то для размещения в своей таблице, вы также можете выбрать задержку использования нагрузки L1d. А затем вычислите числа задержки хранилища так, чтобы хранилище + задержка загрузки = задержка переадресации хранилища, как сейчас. Тогда Intel Atom будет иметь задержку хранилища = -2, потому что у него есть 3c L1d load-use latency, но 1c store-forwarding согласно руководству Agner uarch.

Это труднее, например, для загрузки в регистры XMM или YMM, но все же возможно, если вы определите задержку movq rax, xmm0. Для регистров x87 это сложнее, потому что нет возможности напрямую получить данные из st0 в _10 _ / _ 11_ через ALU вместо сохранения / перезагрузки. Но, возможно, вы могли бы сделать что-то с FP-сравнением, например fucomi, которое напрямую устанавливает целочисленные FLAGS (на процессорах, у которых это есть: P6 и новее).

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


сноска 1. Например, http://instlatx64.atw.hu не пытается, а просто говорит diff . рег. задается в столбце задержки, а полезные данные - только в столбце пропускной способности. Но у них есть линии для MOVD r64, xmm+MOVD xmm, r64 пути туда и обратно, в этом случае всего 2 цикла на IvB так что мы можем быть уверены, что они всего 1 цент в каждую сторону. Не ноль в одну сторону. :П

Но для загрузки в целочисленные регистры они показывают 4-цикловую задержку использования IvB для MOV r32, [m32], потому что, очевидно, они тестируют с [reg + 0..2047] режимом адресации.

https://uops.info/ - это неплохо, но дает довольно слабые границы латентность: IIRC, они создают цикл с циклическим переходом (например, сохранение и перезагрузка или xmm- ›целое и целое-› xmm), а затем задают верхнюю границу задержки, предполагая, что каждый второй шаг составлял только 1 цикл. См. Что делают несколько Значения или диапазоны означают задержку для одной инструкции? подробнее.


Другие источники информации о задержке кеширования:

https://www.7-cpu.com/ содержит полезные сведения для многих других пользователей, даже многие не-x86, такие как ARM, MIPS, PowerPC и IA-64.

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

(со своей страницы Skylake)

  • Задержка кэша данных L1 = 4 цикла для простого доступа через указатель
  • Задержка кэша данных L1 = 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)
person Peter Cordes    schedule 07.01.2019
comment
Благодаря тонну! Долго искал, оказывается у меня какое-то недоразумение по данным. Однако у меня все еще есть сомнения: где рассчитывается мой buf+rax? Я думаю, что это на AGU, а не на ALU, поэтому, когда это похоже на buf+rax, AGU сначала вычислит результат (1 цикл), а затем загрузит данные из кеша L1d (4 цикла). Поскольку я нашел некоторую онлайн-диаграмму, которая показывает, что AGU на портах 2 и 3 подключены к кешу L1d, они отвечают за загрузку данных. Я прав? - person user10865622; 07.01.2019
comment
@ user10865622: Да, он рассчитывается внутри AGU, в зависимости от того, на какой из p2 или p3 отправляется отправка. Вот для чего нужны AGU. - person Peter Cordes; 07.01.2019
comment
О таблице инструкций Агнера, где информация о том, как он вычислял записанные данные? Я не мог найти единственного взгляда на задержку переадресации магазина для его таблиц, я могу найти только эти данные без какой-либо другой информации. - person user10865622; 07.01.2019
comment
@ user10865622: посмотрите на определение терминов в таблице с инструкциями, крайний левый. Там похоронены кое-какие интро. Обновил свой ответ цитатой из соответствующего абзаца. - person Peter Cordes; 07.01.2019