x86中“非临时”内存访问的含义是什么


123

这是一个有点低级的问题。在x86汇编中,有两个SSE指令:

MOVDQA xmmi, m128

MOVNTDQA xmmi, m128

IA-32软件开发人员手册指出 MOVNTDQA NT代表临时性,否则与MOVDQA相同。

我的问题是 非临时性是什么意思?


6
请注意,SSE4.1 MOVNTDQA xmmi, m128是NT加载,而所有其他NT指令都存储,除了prefetchnta。此处接受的答案似乎只是在谈论商店。 这就是我能够发现NT负载的原因。TL:DR:希望CPU对NT提示做一些有用的事情,以最大程度地减少缓存污染,但是它们不会覆盖“正常” WB内存的强序语义,因此它们必须使用缓存。
彼得·科德斯

5
更新:NT 加载可能对大多数CPU(例如Intel SnB系列)的UCSW内存区域没有任何帮助。NT /流存储绝对可以在普通内存上工作。
彼得·科德斯

4
@Peter:你是说USWC记忆对吗?我以前从未听说过UCSW或USWC内存。搜寻错误的首字母缩写无济于事:-)
安德鲁·班布里奇

4
@AndrewBainbridge:是的,WC内存类型属性。不可缓存的推测性写合并。我想我把UnCacheable变成了大写字母,并记住它应该是4个字母长。:P
彼得·科德斯

Answers:


147

非临时性SSE指令(MOVNTI,MOVNTQ等)不遵循常规的缓存一致性规则。因此,非临时存储区后面必须要有SFENCE指令,以便其他处理器及时查看它们的结果。

当产生数据且不再(立即)再次使用数据时,内存存储操作会先读取一条完整的缓存行,然后再修改缓存的数据,这一事实不利于性能。此操作将数据从高速缓存中推出,这可能需要再次使用,以支持即将不再使用的数据。这对于大型数据结构(例如矩阵)尤其如此,这些数据结构先被填充然后在以后使用。在填充矩阵的最后一个元素之前,绝对大小会逐出第一个元素,从而使写入的缓存无效。

对于这种情况和类似情况,处理器为非临时写操作提供支持。在这种情况下,非时间意味着数据将不会很快被重用,因此没有理由对其进行缓存。这些非临时写操作不会先读取高速缓存行,然后再对其进行修改。而是将新内容直接写入内存。

资料来源:http : //lwn.net/Articles/255364/


15
好的答案,我想指出的是,在使用NT指令的处理器上,即使使用非非临时指令(即普通指令),也不会“读取然后修改”行缓存。对于写入不在高速缓存中的行的普通指令,高速缓存中会保留一行,并且掩码会指示该行的哪些部分是最新的。该网页将其称为“商店不停产 ”:ptlsim.org/Documentation/html/node30.html。我找不到更精确的参考,我只是从那些致力于实现处理器模拟器的家伙那里听说过这一点。
Pascal Cuoq

2
实际上,ptlsim.org是一个关于周期精确的处理器模拟器的网站,与那些告诉我“商店没有停顿”的家伙正在做的事情完全一样。如果他们看到此评论,我也最好提一下:unisim.org
Pascal Cuoq 2010年

1
从这里的答案和评论中stackoverflow.com/questions/44864033/…似乎SFENCE不需要。至少在同一线程中。你还能看吗?
Serge Rogatch

1
@SergeRogatch取决于您所讨论的场景,但是是的,在某些情况下,sfenceNT商店需要这样做,而对于普通商店则从来不需要。如其他线程所见,不带NT的存储区不相对于其他存储区(不带NT)进行排序sfence。但是,对于从与存储相同的线程进行读取,则不需要sfence:给定线程将始终按程序顺序查看其自己的存储,而不管它们是否为NT存储。
BeeOnRope

40

Espo几乎可以达到目标。只是想加我两分钱:

“非时间”短语意味着缺少时间局部性。缓存利用两种局部性-空间和时间性,通过使用非时间性指令,您正在向处理器发送信号,告知您您不希望在不久的将来使用该数据项。

我对使用缓存控制指令的手工编码程序集表示怀疑。以我的经验,这些错误导致的臭虫多于任何有效的性能提高。


有关“使用缓存控制指令的手工编码程序集”的问题。我知道您明确地说过“手工编码”的JavaVM之类的东西。这是一个更好的用例吗?JavaVM / Compiler分析了程序的静态和动态行为,并使用了这些非时间性指令。
专利

4
不应该利用问题域,算法或应用程序的已知局部性(或缺乏局部性)。避免缓存污染确实是一项非常有吸引力且有效的优化任务。另外,为什么不喜欢装配呢?编译器可能无法利用大量的获取机会的机会
awdz9nld

5
知识渊博的低级程序员绝对可以胜过小型内核的编译器。这非常适合发表论文和博客文章,而我都做到了。它们也是很好的教学工具,有助于理解“真正”的情况。但是,以我的经验来看,在实践中,如果您有一个包含许多程序员的真实系统,并且正确性和可维护性很重要,那么低级编码的好处几乎总是被风险所抵消。
Pramod

4
@Pramod,相同的论点很容易概括为一般性的优化,而实际上不在讨论范围之内-显然,鉴于我们已经在谈论非时间性指令这一事实,折衷已经被考虑或以其他方式被认为是不相关的
awdz9nld

7

根据《英特尔®64和IA-32架构软件开发人员手册》,第1卷:基本架构,“使用英特尔流SIMD扩展编程(英特尔SSE)”一章:

缓存时态与非时态数据

程序引用的数据可以是临时的(数据将再次使用)或非临时的(数据将被引用一次,并且在不久的将来不会重复使用)。例如,程序代码通常是临时的,而多媒体数据(例如3-D图形应用程序中的显示列表)通常不是临时的。为了有效利用处理器的高速缓存,通常希望高速缓存时间数据而不高速缓存非时间数据。用非临时数据重载处理器的高速缓存有时称为“污染高速缓存”。SSE和SSE2可缓存性控制指令使程序能够以最小化缓存污染的方式将非临时数据写入内存。

非临时加载和存储指令的描述。资料来源:英特尔64和IA-32架构软件开发人员手册,第2卷:指令集参考

加载(MOVNTDQA-加载双四字非时间对齐提示)

如果内存源是WC(写合并)内存类型,则使用非时间提示将双四字从源操作数(第二个操作数)加载到目标操作数(第一个操作数)[...]

处理器不会将数据读取到缓存层次结构中,也不会从内存中获取相应的缓存行到缓存层次结构中。

请注意,正如彼得·科德斯(Peter Cordes)所言,它在当前处理器上的普通WB(回写)内存中没有用,因为NT提示被忽略(可能是因为没有NT感知的硬件预取器),并且采用了完全强序加载语义。 prefetchnta可用作WB存储器的减少污染的负载

存储(MOVNTDQ-使用非时间提示存储打包的整数)

使用非时间提示将源操作数(第二个操作数)中的打包整数移动到目标操作数(第一个操作数),以防止在写入内存时缓存数据。

处理器不会将数据写入缓存层次结构,也不会从内存中提取相应的缓存行到缓存层次结构中。

使用高速缓存写入策略和性能中定义的术语,可以将它们视为可写(无写分配,无写丢失获取)。

最后,回顾一下John McAlpin关于非临时性商店的注释可能会很有趣。


3
SSE4.1 MOVNTDQA仅在WC(不可缓存的Write-Combining)存储区域上执行任何特殊操作,例如视频RAM。在当前硬件的普通WB(回写)内存上,它根本没有用,NT提示将被忽略,并且将应用完整的强序加载语义。 prefetchnta但是,作为减少 WB存储器污染的负载,它可能会很有用。 当前的x86体系结构是否支持非临时负载(来自“正常”内存)?
彼得·科德斯

2
没错,NT存储可以在WB存储器上正常工作,并且顺序较弱,通常是写入较大内存区域的不错选择。但是NT负载不是。纸上的x86手册允许NT提示对WB存储器中的负载执行某些操作,但是在当前的CPU中它什么也没做。(可能是因为没有可识别NT的硬件预取器。)
Peter Cordes

我已将相关信息添加到答案中。非常感谢你。
chus

1
@LewisKelsey:NT 存储确实会覆盖内存类型。这就是为什么可以在WB内存上对其进行弱排序的原因。主要效果是避免了RFO(显然,它们会发送无效消息,甚至在到达内存时也会清除其他脏行)。它们也可能变得无序可见,因此它们不必等到较早的缓存缺失(常规)存储提交后,或者等到较早的缓存缺失负载获取数据后,才能进行查看。即,询问的瓶颈类型在多处理器系统中,每个内核外部的存储器在概念上是否总是平坦/统一/同步的?
彼得·科德斯

1
@LewisKelsey:内存订购机清除可能会杀死UC存储后不应进行的任何负载,如果必要的话,这些负载不应提早完成。除此之外,提交顺序直到商店从无序的后端退出后才起作用。直到执行了存储地址uop之后,才可以执行此操作,此时可以检查该地址的内存类型。存储地址uop在执行时检查TLB。这就是CPU在退役之前可以检测到故障存储的方式。它不能等到SB条目准备好提交给L1d;那时执行已经过去了。
彼得·科德斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.