我们可以在堆内存上使用非临时 mov 指令吗?

Posted

技术标签:

【中文标题】我们可以在堆内存上使用非临时 mov 指令吗?【英文标题】:Can we use non-temporal mov instructions on heap memory? 【发布时间】:2020-07-05 04:58:06 【问题描述】:

在 Agner Fog 的“优化汇编语言中的子例程 - 第 11.8 节缓存控制指令”中,他说:“当回写缓存中发生缓存未命中时,内存写入比读取更昂贵。必须读取整个缓存行在缓存未命中的情况下从内存中进行修改和写回。可以通过使用非临时写指令 MOVNTI、MOVNTQ、MOVNTDQ、MOVNTPD、MOVNTPS来避免。这些指令应该在以下情况下使用写入一个不太可能被缓存的内存位置,并且在可能的缓存行被驱逐之前不太可能再次被读取。根据经验,建议仅在写入内存块时使用非临时写入这比最大级缓存大小的一半还大。”

来自“英特尔 64 和 IA-32 架构软件开发人员手册组合卷 2019 年 10 月”-“这些 SSE 和 SSE2 非临时存储指令通过将正在访问的内存视为写入组合 (WC) 类型来最大限度地减少缓存污染。如果程序使用这些指令之一指定非临时存储并且目标区域的内存类型是回写 (WB)、直写 (WT) 或写入组合 (WC),则处理器将执行以下操作……”

我认为写组合内存只存在于显卡中,而不存在于通用堆内存中——并且通过扩展,上面列出的指令只会在这种情况下有用。如果这是真的,为什么 Agner Fog 会推荐这些说明?英特尔手册似乎暗示它仅对 WB、WT 或 WC 内存有用,但随后他们说正在访问的内存将被视为 WC。

如果这些指令实际上可以用于普通的堆内存写入,有什么限制吗?如何分配写组合内存?

【问题讨论】:

【参考方案1】:

您可以在普通 WB 内存(即堆)上使用像 movntps 这样的 NT 存储。有关 NT 存储与普通存储的更多信息,另请参阅 Enhanced REP MOVSB for memcpy。

对于那些 NT 存储而言,它将其视为 WC,尽管 MTRR 和/或 PAT 将其设置为正常 WB。

英特尔文档告诉您 NT 将“工作”存储在 WB、WT 和 WC 内存中。 (但不是强排序的UC不可缓存内存,当然也不是WP写保护内存)。


您是正确的,通常只有视频 RAM(或可能其他类似的设备内存区域)被映射 WC。不,在 Linux 等普通操作系统下,您无法轻松地在用户空间进程中分配 WC 内存,但您通常不想这样做。

您只能在 WC 内存上使用 SSE4 NT 负载(否则当前的 CPU 会忽略 NT 提示),但是负载的一些缓存污染对于硬件预取和缓存工作来说是一个很小的代价。您可以使用来自 WB 内存的 NT prefetch减少 某些级别的缓存中的污染,例如绕过L2。但这很难调整。

IIRC, normalmov 这样在WC 内存上的存储具有您从NT 存储中获得的存储合并行为。但是你不需要使用 WC 内存来让 NT 存储工作。

【讨论】:

感谢您的确认。幸运的是,我只想做商店,而不是加载。

以上是关于我们可以在堆内存上使用非临时 mov 指令吗?的主要内容,如果未能解决你的问题,请参考以下文章

Windows 逆向使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★

x86 非临时指令:线程本地数据是不是需要围栏?

arm指令中mov和ldr有啥区别?

spark 内存管理

java温习---对象

汇编语言基础总结