2

我在 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 个字节?提前致谢!

4

2 回答 2

7

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

如果 CPU 确实支持它们,那么 CPU 将尝试预取,但如果涉及 TLB 未命中,CPU 将放弃(并且不会预取)。这是大多数人弄错的地方(例如,未能进行“预加载”,您插入一个虚拟读取以强制 TLB 加载,这样就不会阻止预取工作)。

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

如果你预取太晚它没有帮助,如果你太早预取数据可以在使用之前从缓存中逐出(这也没有帮助)。英特尔的“IA-32 英特尔架构优化参考手册”中有一个附录描述了如何计算何时预取,称为“预取调度距离的数学”,您可能应该阅读。

Also don't forget that prefetching can decrease performance (e.g. cause data that is needed to be evicted to make room) and that if you don't prefetch anything the CPU has a hardware prefetcher that will probably do it for you anyway. You should probably also read about how this hardware prefetcher works (and when it doesn't). For example, for sequential reads (e.g. memcmp()) the hardware prefetcher does it for you and using explicit prefetches is mostly a waste of time. It's probably only worth bothering with explicit prefetches for "random" (non-sequential) accesses that the CPU's hardware prefetcher can't/won't predict.

于 2013-01-07T08:45:33.637 回答
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 将数据直接写入内存(理想情况下),而不是读/写缓存行。这实际上在数据结构非常大的情况下非常有用,因为可以避免缓存污染,并且可以缓存更多相关数据。

于 2013-01-07T08:22:20.957 回答