Intel Core i7处理器和缓存行为

Intel Core i7处理器和缓存行为,c,performance,caching,assembly,intel,C,Performance,Caching,Assembly,Intel,我已经在Intel Core i7 CPU(32KB一级数据缓存和64B一级缓存线大小)上运行了以下汇编代码:(在每个4字节10000个元素的数组中迭代1000次) 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 2,503,4

我已经在Intel Core i7 CPU(32KB一级数据缓存和64B一级缓存线大小)上运行了以下汇编代码:(在每个4字节10000个元素的数组中迭代1000次)

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
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
这完全有道理,因为我正在访问内存中的1000*10000=10000个元素,而缓存线为64B(向量中的元素为4B),这意味着每16个元素就有一个一级缓存未命中(因此大约62500000个一级缓存未命中)

现在,我已经“展开”了循环的一部分,代码是:

    .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 how提供以下统计信息:

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
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) 一级缓存加载更少,因为我访问的数据量相同

2) 代码运行速度比第一个版本快6倍?我知道它有
关于无序执行和超标量执行,但我无法详细解释(我想确切了解是什么导致了这种加速)。

坏消息-第二个错误;)

原始代码

.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
第二:

(2.500.000-4)*4+12 = 9.999.996
正好少4倍


只需将第二个示例修复为
cmp eax,10000000

确定:(我已经修复了它。现在缓存命中和加载都正常了。但它的执行速度仍然更快:2.617806762秒。为什么?这只是因为它必须执行更少的跳转指令?展开通常会带来收益。第二件事我们不知道你有哪个i7。另外,如果你不总是加载到ecx,但不同的寄存器(前3个加载是“无效”,因为最后一个总是覆盖ecx,所以CPU可能会看到这一点,并在这里执行一些魔术)。同时检查如果展开8或16次会发生什么。