我在Intel Core i7 CPU(具有32KB L1数据缓存和64B L1缓存行大小)上运行以下汇编代码:(通过一个包含4个字节的10 000 000个元素的数组迭代1000次)
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
Perf给出以下统计数据:
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的元素)这意味着每次都有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
Perf如何给出以下统计数据:
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倍?我知道它有 与无序执行和超标量执行有关,但我无法详细解释这一点(我想了解导致这种加速的原因)。
答案 0 :(得分:4)
坏消息 - 你的第二个错误;)
原始代码
.L3:
mov ecx, DWORD PTR v[0+eax*4]
add eax, 1
cmp eax, 10000000
jl .L3
第二版
.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 <- here
jl .L3
在这两种情况下,您需要加载10万个元素。在两种情况下访问的最大元素地址必须相同,对吧?
所以在第一种情况下,max address是:
(10.000.000-1)*4 = 39.999.996
和第二:
(2.500.000-4)*4+12 = 9.999.996
正好少了4倍。
只需将第二个示例修改为cmp eax, 10000000
。