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

现代x86实现是否可以从一个以上的先前存储进行存储转发?

郑胡媚
2023-03-14
mov [rdx + 0], eax
mov [rdx + 2], eax
mov ax, [rdx + 1]

最后一个2字节加载从紧邻的前一个存储区中获取第二个字节,但从前一个存储区中获取第一个字节。这个加载可以被存储转发吗,还是需要等到前面的两个存储都提交到L1?

请注意,通过这里的存储转发,我包含了任何机制,这些机制可以满足来自仍然在存储缓冲区中的存储的读取,而不是等待它们提交到L1,即使这是一个比“从单个存储转发”的最佳情况更慢的路径。

共有1个答案

空翼
2023-03-14

至少,不是在Haswell、Broadwell或Skylake处理器上。在其他Intel处理器上,限制要么类似(Sandy Bridge、Ivy Bridge),要么更严格(Nehalem,Westmere,Pentium Pro/II/II/4)。在AMD上,也有类似的限制。

来自Agner Fog优秀的优化手册:

处理器可以在某些条件下将存储器写入转发到从相同地址的后续读取。商店转发在以下情况下工作:

  • 无论对齐方式如何,64位或更少的写操作之后都是相同大小和相同地址的读操作。
  • 当一个128位或256位的写操作后面跟着一个相同大小和相同地址的读操作时,完全对齐。
  • 无论对齐方式如何,64位或更少的写操作之后是完全包含在写地址范围内的较小大小的读操作。
  • 任何大小的对齐写入后,对两个半部分进行两次读取,或对四个四分之一部分进行四次读取,等等,它们的自然对齐在写入地址范围内。
  • 当128位或256位的对齐写之后是64位或更少但不跨越8字节边界的读时。

如果存储器块穿过64字节高速缓存行边界,则出现2个时钟的延迟。如果所有数据都有它们的自然对齐,这是可以避免的。

存储区转发在以下情况下失败:

  • 任何大小的写后跟着较大大小的读时
  • 任意大小的写后跟部分重叠的读
  • 当128位的写之后是一个较小的读,穿过两个64位半之间的边界时
  • 当写256位后接128位读越过两个128位半之间的边界时
  • 当256位的写之后是64位或更少的读,越过四个64位四分之一之间的任何边界时

从同一个地址写一次,然后读一次,这样的惩罚很小,甚至没有。

一个64位或更少的写,然后是一个更小的读,当读被偏移但完全包含在写覆盖的地址范围内时,会有1-3个时钟的惩罚。

128位或256位的对齐写入,然后读取两个半位或四个四位中的一个或两个,等等,几乎没有惩罚。一个不适合一半或四分之一的部分读取可能需要额外的11个时钟周期。

具有以下紧密循环的测试:

mov [rsp-16], eax
mov [rsp-12], ebx
mov ecx, [rsp-15]

显示ld_blocks.store_forwardPMU计数器确实在增加。此事件记录如下:

ld_blocks.store_forward[此事件计算加载操作获得阻止存储转发的真正的存储上块阻止代码的次数。这包括:-previer存储与加载冲突(不完全重叠)的情况

>

  • 由于U形限制,存储转发是不可能的

    前面的锁RMW操作不被转发

    存储区设置了无转发位(不可缓存/分页/屏蔽存储区)

    使用全阻塞存储(主要是栅栏和端口I/O)

  •  类似资料:
    • 每个人都知道可以从正在运行的JVM中获得堆转储。另一种方式可能吗?我们可以使用堆转储来启动JVM吗? 这个问题我已经想了很久了。如果这是可能的,它将解决大量的时间,并使支持工程师容易思考。如果我们必须重新创建一些我们的客户所面临的罕见的问题,那么它就会大有帮助。[假设底层硬件和Java运行时是相同的,并且所有的支持文件也存在于文件系统中各自的位置]。 添加注意:这样做的意图不是在OOM发生时,而是

    • 问题内容: 当我尝试从Rails调用存储过程时,出现以下异常: Rails Wiki中 有一个页面讨论用于解决此问题的MySQL适配器的修补程序,但是它已过时,似乎不再起作用。 配置代码正确地启用了存储过程,但是在存储过程调用之后连接仍然不同步并且新方法不再起作用,仍然存在问题。 关于如何使它工作的任何建议? 这是我正在使用的代码: 无论是否返回任何结果,它都会引发相同的异常。 问题答案: 将程序

    • 阅读文档时,并不十分清楚。 我想要的是能够存储和检索简单的json文档。使用CloudSearch,似乎可以以SDF格式存储文档,然后搜索它们,但它只返回文档ID和指定字段的一小部分(我认为是200个字符)。 有没有一种方法来检索完整的文档ID只是使用CloudSearch?还是打算作为搜索和使用主存储服务的附加工具?

    • 我使用redis在我的Spring Boot应用程序中存储会话。我也在使用Spring会话库来实现这一点。我有两个不同的redis实例,即和。一旦有人进入我的应用程序(当然是在登录之后),我希望将他们的会话存储在和服务器中。请注意,这两个redis实例都是主实例,不在任何主从设置中。这是我到目前为止在我的Spring设置。 所以现在,一旦用户登录,他们的会话就存储在中(我在中添加了与美国redis

    • (我不计算单词可寻址的机器,也不计算Alpha(字节可寻址但缺少字节加载/存储指令)。我指的是ISA本身支持的最窄的存储指令。) 在我的研究中,当回答现代x86硬件不能将一个字节存储到内存中吗?时,我发现Alpha AXP省略字节存储的原因是假设它们将被实现为真正的字节存储到缓存中,而不是包含字的RMW更新。(因此,它会使L1d缓存的ECC保护更加昂贵,因为它需要字节粒度而不是32位)。 我假设提

    • Gradle可以设置多个存储库,例如maven和JCenter。但是我意识到gradle总是首先使用jcenter即使我把maven放在jcenter之前(如下所示)。是否有可能使maven(本地回购,并且更快)具有更高的优先级?