我在Intel Vol.2中找到了一个来自多个指令项的推测性数据缓存过程的描述。
例如,lfence
:
处理器可以自由地从区域中推测获取和缓存数据使用WB、WC和WT存储器类型的系统存储器的数量。这推测性获取可以在任何时候发生,并且不与指令执行。因此,它不是关于LFENCE指令的执行;可以将数据带入在执行LFENCE指令。
此外,我从在线资源中发现,推测缓存也会将数据从更远的缓存移动到更近的缓存。
我想知道最强的序列化指令CPUID
是否会阻止跨屏障的推测缓存。
我已经搜索了英特尔第二卷中的CPUID
条目和英特尔第三卷中的"序列化指令"部分。但它并没有显示推测性数据缓存。
LFENCE已经足够强大(至少在实践中),可以阻止CPU实际查看其之后的加载指令,但CPU可以出于其他原因进行推测加载。
要停止这种情况,需要某种超越障碍的前瞻性,以找出要禁用HW预取的地址。这一点都不实际。CPUID或其他序列化指令在停止加载预取方面并不比LFENCE强。
CPU始终允许从WB和WT区域/页面中的内存中推测提取。英特尔的优化手册记录了一些关于其某些CPU型号中硬件预取器的内容,因此在实践中,您可以避免在CPUID之前做可能触发此类预取的事情。
(WC是弱有序的不可缓存+写组合,但纸上也允许推测性提取。在现实生活中,这可能只发生在分支预测失误的阴影下,而不是HW预取。它通常不像WB和WT那样可缓存。)
如果你正在对一个真正的CPU进行微基准测试,那么某些类型的微基准测试的诀窍是找到一个不会触发HW预取的访问模式,或者禁用硬件预取器。
也许理论上你可以有一个x86 CPU,它可以在指令流中提前查看加载/存储指令,并推测性地预取它们,而不是实际执行指令(英特尔对LFENCE的定义会阻止这一点)。我不认为任何事情会阻止它在CPUID上这样做。
可能没有人会设计这样的CPU,因为
- 这不值得晶体管/电源。一旦常规的无序执行能够达到预取,就立即启动预取已经足够好了。除了绝对/RIP相对地址或直接跳转之外,您需要OoO核心的寄存器值才能获得有用的预取地址
- 忽略LFENCE/CPUID是反常的;它们非常罕见,在幽灵党时代,击败对过去负载的推测性"执行"是问题的一部分