我正在进行一些缓存性能测试,需要确保缓存中没有任何“有用”的数据才能计时。
假设 L3 缓存大小为 10MB,是否创建一个大小为 10M/4 = 2,500,000 的浮点数向量,遍历整个向量,对数字进行求和即可清空先前存在于缓存中的所有数据?
我正在进行一些缓存性能测试,需要确保缓存中没有任何“有用”的数据才能计时。
假设 L3 缓存大小为 10MB,是否创建一个大小为 10M/4 = 2,500,000 的浮点数向量,遍历整个向量,对数字进行求和即可清空先前存在于缓存中的所有数据?
是的,这应该足以清除有用数据的L3缓存。
我做过类似类型的测量,并通过使用英特尔的缓存计数器进行交叉验证,以验证在我的测试期间我遇到了预期数量的L3缓存未命中。
如果你想要绝对确定,你也应该使用计数器。特别地,在大多数英特尔架构中,你可以使用“事件选择2EH,Umask 41H”来测量最后一级缓存未命中。
有关这些计数器的详细信息,请参见Intel手册。
这取决于你为了获得保证愿意采取多么疯狂的方式。
x86_64 L3缓存是物理索引的,虽然在虚拟空间中以10MiB为单位的线性块几乎肯定会在轻载机器上物理连续,但无法保证。
例如,Sandy和Ivy Bridge将L3缓存划分为2MiB片段,并具有16路组相联(128kiB步幅),因此您可以通过进行MAP_HUGETLB
mmap()
调用来保证物理覆盖范围,假设使用标准的2-4MiB巨大页面。
此外,由于每个片段(至少在新的Sandy/Ivy Bridge上)都附加到不同的核心,并且给定物理地址位于哪个片段是由一些低/中序地址位的哈希确定的,所以您可能需要创建一个略大于L3大小的数组,以抵消微不足道的重叠。
此时,线性地多次擦除数组应该就可以解决问题。
另一个选择是使用一些ISA提供的专用缓存失效指令。例如,x86有wbinvd
用于此目的(或clflush
用于单行)。
http://x86.renejeschke.de/html/file_module_x86_id_325.html
一个问题是它需要 ring-0 权限。另一个问题是它不能保证刷新在任何序列化点之前完成,因此不能足够保证系统的不易失性,但只要您可以防止随后的 WB 占用您的内存带宽,这可能足够进行基准测试。
memset()
函数清空任何大块连续内存即可。一些处理器具有哈希L3缓存。因此,由于冲突,恰好与缓存大小相同的连续内存块可能不足够。但我认为,通过拉取几百MB应该就足够了。 - Mysticial