C++ 如何清除L1、L2和L3缓存?

C++ 如何清除L1、L2和L3缓存?,c++,performance,caching,cpu,cpu-architecture,C++,Performance,Caching,Cpu,Cpu Architecture,我正在做一些缓存性能测量,我需要在计时之前确保缓存中没有“有用”的数据 假设一个三级缓存是10MB,那么创建一个10M/4=2500000浮点的向量就足够了,遍历整个向量,对数字求和,这将清空整个缓存中在遍历向量之前的所有数据吗?是,这应该足以刷新有用数据的L3缓存 我曾进行过类似类型的测量,并通过使用英特尔的缓存计数器进行交叉验证,以验证我在测试期间是否发生了预期的L3缓存未命中次数 如果你想绝对肯定,你也应该使用计数器。特别是,您可以在大多数英特尔体系结构中使用事件选择2EH、Umask 4

我正在做一些缓存性能测量,我需要在计时之前确保缓存中没有“有用”的数据


假设一个三级缓存是10MB,那么创建一个10M/4=2500000浮点的向量就足够了,遍历整个向量,对数字求和,这将清空整个缓存中在遍历向量之前的所有数据吗?

是,这应该足以刷新有用数据的
L3
缓存

我曾进行过类似类型的测量,并通过使用英特尔的缓存计数器进行交叉验证,以验证我在测试期间是否发生了预期的
L3
缓存未命中次数

如果你想绝对肯定,你也应该使用计数器。特别是,您可以在大多数英特尔体系结构中使用
事件选择2EH、Umask 41H
来测量最后一级缓存未命中


有关这些计数器的详细信息,请参见。

这取决于您试图获得担保的疯狂程度

x86_64 L3缓存是物理索引的,虽然在虚拟空间中线性的10Mb数据块几乎肯定会在一台内存负载较轻的机器上物理连续,但这并不能保证

例如,Sandy和Ivy Bridge在2MiB片中有L3缓存,具有16路集关联性(128kiB步幅),因此您可以通过执行
MAP_HUGETLB
mmap()
调用来保证物理覆盖,假设标准的2-4MiB大页面

此外,由于每个片(至少在新的Sandy/Ivy桥上)都连接到不同的核心,并且给定的物理地址驻留在哪个片上是由一些低/中阶地址位的散列确定的,因此您可能必须使数组略大于L3的大小,以抵消微小的不均匀重叠


此时,线性地擦洗阵列几次就可以了。

另一种选择是使用一些ISA提供的专用缓存失效指令。例如,x86具有用于此目的的
wbinvd
(或用于单行的
clflush

一个问题是它需要环-0权限。另一个原因是,它不能保证刷新在任何序列化点之前完成,因此它不足以保证系统的非易失性,但它可能足以进行基准测试,只要您可以防止随后的WBs占用内存带宽


如果您能够克服这些问题,在某些情况下,它可能是一个更好的解决方案,而不仅仅是为了确保刷新缓存而检查一些大型数据结构。一些CPU可能会决定避免缓存他们认为在将来不会被重用的回迁(关于这些选项有几篇文章,至少有一些文章声称它是在真正的CPU中实现的)

如果您想清除缓存,只需从中提取一组与您的测试数据无关的数据。@Mystical嘿Mystical,我的矢量概念得到你的认可了吗?250万够了吗?我不确定,因为缓存集的关联性。是的,只是
memset()
任何大的连续内存块。某些处理器具有散列三级缓存。因此,可能由于冲突,与缓存大小完全相同的连续内存块不够。但我想说,拉几百MB就足够了。问题和答案都是关于三级缓存的,但标题是关于一级/二级/三级缓存的。您应该知道,一级缓存和有时二级缓存是每个核心的,通过清除三级缓存,如果您的程序切换核心,您仍然可能会遇到问题。您好@merlin2011,您可以发布您在某个站点上执行的测试,并给我查看它的链接吗?我试图执行相同的测试,以证明L3缓存确实已清理,但我无法做到这一点。