2013-01-07 20 views
2

我碰到了NASM文档中的以下说明,但我无法完全理解它们的正面或反面。不幸的是,关于这些指令的英特尔文档也有些缺乏。NASM预取

PREFETCHNTA m8    ; 0F 18 /0  [KATMAI] 
PREFETCHT0 m8     ; 0F 18 /1  [KATMAI] 
PREFETCHT1 m8     ; 0F 18 /2  [KATMAI] 
PREFETCHT2 m8     ; 0F 18 /3  [KATMAI] 

任何人都可能提供一个简明的例子说明,说在一个给定的地址缓存256字节?提前致谢!

回答

6

这些指令提示用于暗示CPU尝试将高速缓存行预取到高速缓存中。因为它们是提示,CPU可以完全忽略它们。

如果CPU确实支持它们,CPU将尝试预取,但如果涉及到TLB未命中,则会放弃(并且不会预取)。这是大多数人错误的地方(例如,未能执行“预加载”,在那里插入一个虚读来强制TLB加载,以防止预取无法工作)。

预取的数据量为32个字节或更多,具体取决于CPU等。您可以使用CPUID来确定实际大小(CPUID函数0x00000004,EBX位0到31中返回的“系统一致性行大小” 。

如果您预取得太晚,这并没有帮助,并且如果预取得太早,数据可能会在使用前从缓存中清除(这也无济于事)。英特尔的“IA-32英特尔架构优化参考手册”中有一个附录,介绍如何计算何时预取,称为“预取计划距离的数学”,您应该阅读。

另外不要忘记,预取可能会降低性能(例如,导致需要驱逐以腾出空间的数据),并且如果您不预取任何内容,则CPU有硬件预取程序,可能会为您执行此操作无论如何。您应该也可以阅读这个硬件预取程序是如何工作的(以及什么时候没有)。例如,对于顺序读取(例如memcmp()),硬件预取程序会为您执行此操作,并且使用显式预取大多浪费时间。对于CPU的硬件预取器无法/不会预测的“随机”(非顺序)访问,显式预取可能只是值得困扰。

1

在筛选了大量优化的memcmp函数之类的示例之后,我已经想出了如何有效地使用这些指令(有点)。

这些指令意味着一个32字节的缓存“行”,这是我最初错过的东西。因此,高速缓存256字节缓冲器中的L1和L2,下面的指令集可以使用:

prefetcht1 [buffer] 
prefetcht1 [buffer+32] 
prefetcht1 [buffer+64] 
prefetcht1 [buffer+96] 
prefetcht1 [buffer+128] 
prefetcht1 [buffer+160] 
prefetcht1 [buffer+192] 
prefetcht1 [buffer+224] 

T0的后缀指示CPU将其预取到整个高速缓存层次结构。

t1指示将数据缓存到L1,L2等中。

t2继续这一趋势,预取到L2等。

“nta”后缀更容易混淆,因为它告诉CPU将数据直接写入内存(理想情况下),而不是读取/写入缓存行。这对于难以置信的大数据结构实际上可能非常有用,因为可以避免缓存污染,并且可以缓存更多相关数据。

+0

你在考虑新界的商店。 'prefetchnta'是非常不同的,因为它仍然是关于加载,而不是存储。它获取到L1,同时最大限度地减少对其他级别缓存的污染。 –

+0

在P4之后,64B高速缓存行已经成为所有x86 CPU的标准配置。只有奔腾III和更早的版本有32B线。 –