当前位置: 首页 > 知识库问答 >
问题:

无序执行是否会导致推测性内存访问?

闾丘冠玉
2023-03-14

当无序处理器遇到以下情况时

LOAD R1, 0x1337
LOAD R2, $R1
LOAD R3, 0x42

假设所有访问都将导致缓存未命中,处理器能否在请求$R1甚至0x1337之前请求内存控制器请求0x42的内容?如果是这样,假设访问$R1将导致异常(例如,分段错误),我们可以认为0x42是推测性加载的,对吗?

顺便说一下,当加载存储单元向内存控制器发送请求时,它可以在接收到对前一个的回答之前发送第二个请求吗?

我的问题没有特别针对任何架构。欢迎与任何主流架构相关的答案。

共有3个答案

阮华美
2023-03-14

与x86相关:为什么要刷新由其他逻辑处理器导致的内存顺序冲突的管道?。可观察的结果将遵守x86排序规则,但微体系结构上是的,它可以提前加载。(当然,这是来自缓存;硬件预取是不同的)。

如果地址没有为一次加载做好准备,OoO exec CPU确实会对加载执行进行重新排序。或者如果它在缓存中丢失,那么以后的加载可以在数据到达之前运行。但是在x86上,为了保持正确性。强内存模型(程序订购带有存储转发的存储缓冲区),核心根据ISA的纸上内存模型保证检查最终结果是否合法。(即从之前加载的缓存行仍然有效,因此仍然包含我们现在允许加载的数据)。如果没有,则对依赖于这种可能不安全的猜测的正在运行的指令进行核攻击,并回滚到已知的安全状态。

因此,现代x86在保持内存模型规则的同时(大多数情况下)获得了宽松的负载顺序,其中每个负载实际上都是一个获取负载。但如果你做了管道不喜欢的事情,例如虚假共享(这已经够糟糕了),那么就要付出管道核武器的代价。

其他具有强内存模型(Sparc TSO)的CPU可能不会这么激进。弱内存模型允许稍后的加载提前完成。

当然,这是从缓存中读取;只有在缓存未命中时,/a内存控制器才能看到按需加载请求。但是硬件预取器可以从CPU异步访问内存;这就是他们在CPU运行加载数据的指令之前将数据放入缓存的方式,理想情况下可以避免缓存丢失。

是的,内存子系统是流水线的,就像Skylake中每个核心有12到16个未完成的请求。(L1为12个LFB

朱和惬
2023-03-14

这似乎也是具有多个负载存储单元的超标量CPU的逻辑结论。如今,多通道内存控制器非常常见。

在无序指令执行的情况下,需要花费大量的逻辑来确定指令是否依赖于流中的其他指令—不仅依赖于寄存器,还依赖于内存上的操作。处理异常也有大量的逻辑:CPU需要完成流中直到故障的所有指令(或者,将其中的一些部分卸载到操作系统上)。

就大多数应用程序看到的编程模型而言,效果从来都不明显。正如内存所看到的那样,负载并不总是按照预期的顺序发生——但在使用缓存时无论如何都是如此。

显然,在加载和存储顺序很重要的情况下,例如在访问设备寄存器时,必须禁用OOE。POWER体系结构为此提供了出色的EIEIO指令。

ARM Cortex家族的一些成员提供OOE,我怀疑由于这些设备的功率限制,以及明显缺乏强制订购的说明,负载存储总是按顺序完成的

公冶翰池
2023-03-14

问题的答案取决于CPU的内存排序模型,这与允许无序执行的CPU不同。如果CPU实现了总存储排序(例如x86或Sparc),那么您的问题的答案是0x42不会在0x1337之前加载

如果cpu实现了宽松的内存模型(例如IA-64、PowerPC、alpha),那么在没有内存Geofence指令的情况下,所有关于哪个将首先访问的赌注都将取消。除非您正在执行IO或处理多线程代码,否则这应该没有什么相关性。

您应该注意到,一些CPU(如安腾)确实有宽松的内存模型(因此读取可能无序),但没有任何无序执行逻辑,因为它们希望编译器以最佳方式对指令和推测指令进行排序,而不是在OOE上花费硅空间

 类似资料:
  • 问题内容: 我正在编写一个测试程序,如下所示: 当用户单击按钮A时,它将打开50个JFrame。 当用户单击按钮B时,它将放置所有通过单击按钮A显示的JFrame。 我发现单击按钮B后内存不会减少。我使用任务管理器(在Windows中为+ + ,并检查“ java”的内存使用情况)确定了这一点。 问题答案: 是的,没有办法,无法解决(不仅在Java PL中), 1)实际上,不要在运行时/运行时创建

  • 我想知道为什么需要内存障碍,我读了一些关于这个Topic的文章 有人说这是因为cpu无序执行,而其他人说这是因为缓存一致性问题导致缓冲区存储和队列失效<那么,需要记忆障碍的真正原因是什么?cpu无序执行或缓存一致性问题?或者两者都有?cpu无序执行是否与缓存一致性有关?x86和arm之间有什么区别?

  • 我有一些和等,但是我没有设置。你觉得会是那样吗? 你有什么想法或建议吗? PS:该应用程序在Ubuntu机器上运行 多谢.

  • std::list<TCHAR> ReturnList() 出栈后访问list是否可能出现THCAR被释放导致访问异常? 两个函数放的TCHAR* ,用完这个list后需要list.clear()吗?

  • 这只是出于好奇。 如果是这样,那么扩展到一个极端的情况,如果您的内存以某种方式结束了超级碎片(例如,每隔一个字节都被分配为ala 我想站台不重要? 很抱歉提出了一个扩展的问题,但这也会发生在其他语言中吗,比如Java/C#?

  • 可以是任何类,甚至可以是。如果是值类型,执行上面的检查是否会导致装箱?我的理解是,这与调用相同,后者接受两个参数,如果是值类型,如果我理解正确的话,这两个参数中的任何一个都会导致装箱。 如果上述情况确实导致装箱,是否有更好的方法来做到这一点而不导致装箱发生?我知道有,但对于,这是,我希望查看这个值是否为,而不对其进行装箱。此外,我希望以一种既满足值类型又满足引用类型的方式来实现这一点。