我们正在尝试使用 Intel CLFLUSH 指令在用户空间刷新 Linux 中进程的缓存内容。
我们创建一个非常简单的 C 程序,首先访问一个大数组,然后调用 CLFLUSH 刷新整个数组的虚拟地址空间。我们测量 CLFLUSH 刷新整个数组所需的延迟。程序中数组的大小是一个输入,我们将输入从 1MB 更改为 40MB,步长为 2MB。
根据我们的理解,CLFLUSH 应该刷新内容在缓存中。因此,我们期望看到刷新整个数组的延迟首先随数组的大小线性增加,然后在数组大小大于 20MB(即我们程序的 LLC 的大小)后延迟应该停止增加。
然而实验结果却相当令人惊讶,如图所示。当数组大小大于 20MB 后,延迟不会停止增加。
我们想知道,如果该地址尚未在缓存中,那么在 CLFLUSH 将地址从缓存中刷新之前,CLFLUSH 是否可能会引入该地址?
我们还尝试在Intel软件开发人员手册中进行搜索,但没有找到任何关于如果地址不在缓存中CLFLUSH将做什么的解释。
下面是我们用来绘制该图的数据。第一列是数组的大小(以 KB 为单位),第二列是刷新整个数组的延迟(以秒为单位)。
任何建议/意见都非常感激。
[修改的]
前面的代码是不必要的。 CLFLUSH 在用户空间中可以更容易地完成,尽管它具有相似的性能。所以我删除了那些乱七八糟的代码,以免造成混乱。
SCENARIO=Read Only
1024,.00158601000000000000
3072,.00299244000000000000
5120,.00464945000000000000
7168,.00630479000000000000
9216,.00796194000000000000
11264,.00961576000000000000
13312,.01126760000000000000
15360,.01300500000000000000
17408,.01480760000000000000
19456,.01696180000000000000
21504,.01968410000000000000
23552,.02300760000000000000
25600,.02634970000000000000
27648,.02990350000000000000
29696,.03403090000000000000
31744,.03749210000000000000
33792,.04092470000000000000
35840,.04438390000000000000
37888,.04780050000000000000
39936,.05163220000000000000
SCENARIO=Read and Write
1024,.00200558000000000000
3072,.00488687000000000000
5120,.00775943000000000000
7168,.01064760000000000000
9216,.01352920000000000000
11264,.01641430000000000000
13312,.01929260000000000000
15360,.02217750000000000000
17408,.02516330000000000000
19456,.02837180000000000000
21504,.03183180000000000000
23552,.03509240000000000000
25600,.03845220000000000000
27648,.04178440000000000000
29696,.04519920000000000000
31744,.04858340000000000000
33792,.05197220000000000000
35840,.05526950000000000000
37888,.05865630000000000000
39936,.06202170000000000000