Я играл с кодом в этом ответе, слегка меняя его:
BITS 64
GLOBAL _start
SECTION .text
_start:
mov ecx, 1000000
.loop:
;T is a symbol defined with the CLI (-DT=...)
TIMES T imul eax, eax
lfence
TIMES T imul edx, edx
dec ecx
jnz .loop
mov eax, 60 ;sys_exit
xor edi, edi
syscall
Без lfence
я результаты, которые я получаю, согласуются с статическим анализом в этом ответе.
Когда я lfence
единый lfence
я ожидаю, что CPU выполнит последовательность imul edx, edx
k-й итерации параллельно с imul eax, eax
последовательностью следующей (k + 1-й) итерации.
Что-то вроде этого (вызов A imul eax, eax
sequence и D imul edx, edx
one):
|
| A
| D A
| D A
| D A
| ...
| D A
| D
|
V time
Принимая более или менее одинаковое количество циклов, но для одного непарного параллельного выполнения.
Когда я измеряю количество циклов, для исходной и модифицированной версии, с taskset -c 2 ocperf.py stat -r 5 -e cycles:u '-x './main-$T
для T
в диапазон ниже я получаю
T Cycles:u Cycles:u Delta
lfence no lfence
10 42047564 30039060 12008504
15 58561018 45058832 13502186
20 75096403 60078056 15018347
25 91397069 75116661 16280408
30 108032041 90103844 17928197
35 124663013 105155678 19507335
40 140145764 120146110 19999654
45 156721111 135158434 21562677
50 172001996 150181473 21820523
55 191229173 165196260 26032913
60 221881438 180170249 41711189
65 250983063 195306576 55676487
70 281102683 210255704 70846979
75 312319626 225314892 87004734
80 339836648 240320162 99516486
85 372344426 255358484 116985942
90 401630332 270320076 131310256
95 431465386 285955731 145509655
100 460786274 305050719 155735555
Как можно объяснить значения Cycles:u lfence
?
Я бы ожидал, что они будут похожи на те, что у Cycles:u no lfence
так как один lfence
должен предотвращать параллельную реализацию первой итерации для двух блоков.
Я не думаю, что это из - за lfence
накладных расходов, поскольку я считаю, что должно быть постоянным для всех T
s.
Я хотел бы исправить то, что неправильно с моим forma mentis, когда речь идет о статическом анализе кода.