我已经运行以下汇编代码:(它通过1000万个元素,每个4字节数组重复1000次)在Intel Core i7 CPU(具有32KB L1数据高速缓存和64B L1高速缓存行大小)英特尔酷睿i7处理器和高速缓存行为
main:
.LFB0:
.cfi_startproc
mov edx, 1000
jmp .L2
.L3:
mov ecx, DWORD PTR v[0+eax*4]
add eax, 1
cmp eax, 10000000
jl .L3
sub edx, 1
je .L4
.L2:
mov eax, 0
jmp .L3
.L4:
mov eax, 0
ret
.cfi_endproc
逆足给出下列数据:
10,135,716,950 L1-dcache-loads
601,544,266 L1-dcache-load-misses # 5.93% of all L1-dcache hits
4.747253821 seconds time elapsed
这使得完全感,因为我访问1 000 * 10 000 000 = 10 000 000 000在存储器元件,和所述缓存行是64B(带有一个向量为4 B的元素),这意味着在e处一个L1缓存未命中非常16个元素(因此约625 000 000个L1缓存未命中)。
现在,我已经“展开”循环的一部分,代码为:
.cfi_startproc
mov edx, 1000
jmp .L2
.L3:
mov ecx, DWORD PTR v[0+eax*4]
mov ecx, DWORD PTR v[0+eax*4 + 4]
mov ecx, DWORD PTR v[0+eax*4 + 8]
mov ecx, DWORD PTR v[0+eax*4 + 12]
add eax, 4
cmp eax, 2500000
jl .L3
sub edx, 1
je .L4
.L2:
mov eax, 0
jmp .L3
.L4:
mov eax, 0
ret
.cfi_endproc
逆足如何给出了如下数据:
2,503,436,639 L1-dcache-loads
123,835,666 L1-dcache-load-misses # 4.95% of all L1-dcache hits
0.629926637 seconds time elapsed
我不明白为什么?
1)因为我正在访问相同数量的数据,所以L1缓存负载较少?
2)代码运行速度比第一个版本快6倍?我知道它有 与无序执行和超标量执行有关,但我无法详细解释这一点(我想明白导致这种加速的确切原因)。
确定:(我已经修复了,现在缓存命中并且加载正常,但仍然能够更快地执行:2.617806762秒,这只是因为它必须执行更少的跳转指令? – SebiSebi
10展开通常会带来收益。我们不知道你有哪个i7,还要检查如果你不总是加载到ecx但是不同的寄存器会发生什么(前3个加载是“无效的”,因为最后一个总是覆盖ecx,所以CPU可能会看到并做一些魔术这里),并检查如果你展开8次或16次会发生什么。 – Anty