和
MOVDQA xmmi,m128
IA-32软件开发人员手册表示MOVNTDQA中的“NT”代表“非临时的”,其他方面与MOVDQA相同。
MOVNTDQA xmmi,m128
我的问题是,“非临时的”的意思是什么?
非暂态SSE指令(MOVNTI,MOVNTQ等)不遵循常规缓存一致性规则。因此,为了使它们的结果及时地被其他处理器看到,非暂态存储必须跟随一个SFENCE指令。
当数据产生且(立即)不再被消费时,存储操作会先读取整个缓存行,然后修改缓存数据的事实对性能是有害的。这个操作将数据从缓存中推出,而这些数据可能在以后还需要使用,而放弃这些缓存数据而使用不久的数据。对于像矩阵这样的大型数据结构,填充后稍后再使用。在矩阵的最后一个元素填充之前,其巨大的大小会将第一个元素逐出缓存,使写入的缓存失效。
针对此类情况,处理器提供非暂态写入操作的支持。在这个上下文中,非暂态意味着数据不会很快被重复使用,因此没有理由将其缓存。这些非暂态写操作不读取缓存行并修改它,而是直接将新内容写入内存。
SFENCE
可能不是必需的。至少在同一个线程中。你也可以看一下吗? - Serge Rogatchsfence
来进行 NT 存储,而对于普通存储来说则从不需要。如果没有 sfence
,NT 存储与其他存储(无论是否为 NT 存储)之间的顺序关系将不会被其他线程看到。然而,对于执行存储操作的同一线程的读取操作,您永远不需要 sfence
:给定线程始终会按照程序顺序查看其自己的存储,无论它们是 NT 存储还是其他类型的存储。 - BeeOnRopeEspro的观点基本上非常准确。只想补充一下:
“非时间性”指缺乏时间局部性。缓存利用两种局部性 - 空间和时间,通过使用非时间性指令,您向处理器发出信号,表明您不希望在不久的将来使用数据项。
我对使用缓存控制指令的手动编码汇编有些怀疑。根据我的经验,这些东西会导致更多的错误,而不是有效的性能提升。
[...] 处理器不会将数据读入高速缓存层次结构,也不会从内存中获取相应的缓存行到高速缓存层次结构中。
需要注意的是,正如Peter Cordes所评论的,对于当前处理器上的普通WB(写回)内存而言,它并不有用,因为NT提示被忽略了(可能是因为没有NT-aware HW prefetchers),完全遵循强排序加载语义。 prefetchnta
可以用作来自WB内存的污染减少负载操作。
存储(MOVNTDQ-使用非临时提示存储打包整数)
使用非临时提示,将源操作数(第二个操作数)中的打包整数移动到目标操作数(第一个操作数)中,以防止在写入内存时缓存数据。
[...] 处理器不会将数据写入高速缓存层次结构,也不会从内存中获取相应的缓存行到高速缓存层次结构中。
使用Cache Write Policies and Performance中定义的术语,它们可以被视为写入绕过(不写分配,不在写缺失时获取)。
最后,有必要回顾John McAlpin有关非临时存储的注意事项。
MOVNTDQA
指令只对WC(不可缓存的写组合)内存区域有特殊作用,例如视频内存。它在当前硬件上对普通的WB(写回)内存没有任何用处,NT提示被忽略,并且完全遵循强顺序加载语义。prefetchnta
指令可能是有用的,因为它可以从WB内存中减少污染。当前的x86架构支持从“普通”内存进行非暂态加载吗? - Peter Cordes
MOVNTDQA xmmi, m128
是一种非临时性加载指令(NT load),而所有其他NT指令都是存储指令,除了prefetchnta
。这个被接受的答案似乎只谈到了存储指令。这是我在NT加载方面找到的内容。简而言之,CPU会希望使用NT提示来最小化缓存污染,但它们不会覆盖“正常”写回内存的强序语义,所以它们还是需要使用缓存。 - Peter Cordes