gpt4 book ai didi

performance - 为什么修改指令会导致 x86 上的大量 i-cache 和 i-TLB 未命中?

转载 作者:行者123 更新时间:2023-12-04 15:39:05 25 4
gpt4 key购买 nike

以下代码片段仅使用一个 RET 指令创建一个函数(有趣)。
循环重复调用该函数并在返回后覆盖RET指令的内容。

#include <sys/mman.h>
#include<stdlib.h>
#include<unistd.h>
#include <string.h>

typedef void (*foo)();
#define RET (0xC3)

int main(){
// Allocate an executable page
char * ins = (char *) mmap(0, 4096, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE| MAP_ANONYMOUS, 0, 0);
// Just write a RET instruction
*ins = RET;
// make fun point to the function with just RET instruction
foo fun = (foo)(ins);
// Repeat 0xfffffff times
for(long i = 0; i < 0xfffffff; i++){
fun();
*ins = RET;
}
return 0;
}

X86 Broadwell 机器上的 Linux 性能具有以下 icache 和 iTLB 统计信息:

perf stat -e L1-icache-load-misses -e iTLB-load-misses ./a.out

'./a.out' 的性能计数器统计信息:
   805,516,067      L1-icache-load-misses                                       
4,857 iTLB-load-misses

32.052301220 seconds time elapsed

现在,在不覆盖 RET 指令的情况下查看相同的代码。
#include <sys/mman.h>
#include<stdlib.h>
#include<unistd.h>
#include <string.h>

typedef void (*foo)();
#define RET (0xC3)

int main(){
// Allocate an executable page
char * ins = (char *) mmap(0, 4096, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE| MAP_ANONYMOUS, 0, 0);
// Just write a RET instruction
*ins = RET;
// make fun point to the function with just RET instruction
foo fun = (foo)(ins);
// Repeat 0xfffffff times
for(long i = 0; i < 0xfffffff; i++){
fun();
// Commented *ins = RET;
}
return 0;
}

这是同一台机器上的性能统计信息。

perf stat -e L1-icache-load-misses -e iTLB-load-misses ./a.out

'./a.out' 的性能计数器统计信息:
        11,738      L1-icache-load-misses                                       
425 iTLB-load-misses

0.773433500 seconds time elapsed

请注意,覆盖指令会导致 L1-icache-load-misses 从 11,738 增长到 805,516,067 —— 多种增长。
另请注意,iTLB-load-misses 从 425 增长到 4,857——增长幅度相当大,但与 L1-icache-load-misses 相比有所减少。
运行时间从 0.773433500 秒增长到 32.052301220 秒——增长了 41 倍!

如果指令占用空间如此之小,目前还不清楚为什么 CPU 会导致 i-cache 未命中。两个示例的唯一区别是修改了指令。假设 L1 iCache 和 dCache 是分开的,有没有办法将代码安装到 iCache 中,以避免缓存 i-cache 未命中?

此外,为什么 iTLB 未命中数会增长 10 倍?

最佳答案

Granted the L1 iCache and dCache are separate, isn't there a way to install code into iCache so that the cache i-cache misses can be avoided?



不。

如果你想修改代码 - 唯一可以去的路径如下:
  • 存储日期执行引擎
  • 存储缓冲和转发
  • 一级数据缓存
  • 统一二级缓存
  • L1 指令缓存

  • 请注意,您也错过了 μOP 缓存。

    这由 this diagram 说明1,我认为这是足够准确的。

    我怀疑 iTLB 未命中可能是由于常规 TLB 刷新。在没有修改的情况下,您不会受到 iTLB 未命中的影响,因为您的指令实际上来自 μOP 缓存。

    如果他们不这样做,我不太确定。我认为 L1 指令缓存是虚拟寻址的,因此如果命中,则无需访问 TLB。

    1:不幸的是,该图像的版权限制非常严格,因此我避免突出显示路径/内联图像。

    关于performance - 为什么修改指令会导致 x86 上的大量 i-cache 和 i-TLB 未命中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52356457/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com