порт (p2 или p3), так как результат входящей нагрузки, возможно, придется немедленно передать обратно в AGU. Теперь в случае конкурирующей операции хранилища, возможно, вместо этого используется AGU, и оптимизация прерывается, что приводит к повторению 9 циклов.
ла у меня есть установка ниже на IvyBridge, я вставлю код измерения полезной нагрузки в закомментированном месте. Первые 8 байтовbuf
хранить адресbuf
Сам я использую это для создания переносимых зависимостей:
section .bss
align 64
buf: resb 64
section .text
global _start
_start:
mov rcx, 1000000000
mov qword [buf], buf
mov rax, buf
loop:
; I will insert payload here
; as is described below
dec rcx
jne loop
xor rdi, rdi
mov rax, 60
syscall
Дело 1:Я вставляю в расположение полезной нагрузки:
mov qword [rax+8], 8
mov rax, [rax]
perf
показывает, что цикл составляет 5,4 с / итера. Это несколько понятно, потому что задержка L1d составляет 4 цикла.
Я изменяю порядок этих двух инструкций:
mov rax, [rax]
mov qword [rax+8], 8
Результат неожиданно становится 9c / iter. Я не понимаю почему. Поскольку первая инструкция следующей итерации не зависит от второй инструкции текущей итерации, этот параметр не должен отличаться от случая 1.
Я также использовал инструмент IACA для статического анализа этих двух случаев, но этот инструмент ненадежен, потому что он предсказывает один и тот же результат в 5,71 с / итер для обоих случаев, что противоречит эксперименту.
случай 3:Затем я вставляю неактуальныеmov
инструкция к случаю 2:
mov rax, [rax]
mov qword [rax+8], 8
mov rbx, [rax+16]
Теперь результат становится 6.8c / iter. Но как может быть неактуальноmov
вставлен ли прирост скорости с 9с / итер до 6,8с / ит?
Инструмент IACA предсказывает неверный результат, как в предыдущем случае, он показывает 5.24c / iter.
Я сейчас совершенно сбит с толку, как понять приведенные выше результаты?
Изменить для получения дополнительной информации:В случаях 1 и 2 есть адресrax+8
, Те же результаты остаются для случаев 1 и 2, еслиrax+8
изменено наrax+16
или жеrax+24
, Но что-то удивительное случается, когда оно меняется наrax+32
: случай 1 становится 5,3c / iter, случай 2 внезапно становится 4,2c / iter.
perf
Мероприятия:$ perf stat -ecycles,ld_blocks_partial.address_alias,int_misc.recovery_cycles,machine_clears.count,uops_executed.stall_cycles,resource_stalls.any ./a.out
случай 1 для[rax+8]
:
5,429,070,287 cycles (66.53%)
6,941 ld_blocks_partial.address_alias (66.75%)
426,528 int_misc.recovery_cycles (66.83%)
17,117 machine_clears.count (66.84%)
2,182,476,446 uops_executed.stall_cycles (66.63%)
4,386,210,668 resource_stalls.any (66.41%)
дело 2 для[rax+8]
:
9,018,343,290 cycles (66.59%)
8,266 ld_blocks_partial.address_alias (66.73%)
377,824 int_misc.recovery_cycles (66.76%)
10,159 machine_clears.count (66.76%)
7,010,861,225 uops_executed.stall_cycles (66.65%)
7,993,995,420 resource_stalls.any (66.51%)
случай 3 для[rax+8]
:
6,810,946,768 cycles (66.69%)
1,641 ld_blocks_partial.address_alias (66.73%)
223,062 int_misc.recovery_cycles (66.73%)
7,349 machine_clears.count (66.74%)
3,618,236,557 uops_executed.stall_cycles (66.58%)
5,777,653,144 resource_stalls.any (66.53%)
дело 2 для[rax+32]
:
4,202,233,246 cycles (66.68%)
2,969 ld_blocks_partial.address_alias (66.68%)
149,308 int_misc.recovery_cycles (66.68%)
4,522 machine_clears.count (66.68%)
1,202,497,606 uops_executed.stall_cycles (66.64%)
3,179,044,737 resource_stalls.any (66.64%)