作者:翔未央图_971 | 来源:互联网 | 2022-12-11 07:16
我一直试图谷歌我的问题,但老实说,我不知道如何简洁地陈述问题.
假设我在多核Intel系统中有两个线程.这些线程在同一个NUMA节点上运行.假设线程1写入X一次,然后只是偶尔读取它向前移动.进一步假设,线程2连续读取X. 如果我不使用内存栅栏,在线程1写入X和线程2看到更新值之间可以有多长时间?
我知道X的写入将转到存储缓冲区并从那里到缓存,此时MESIF将启动,线程2将通过QPI查看更新的值.(或者至少这是我收集到的).我假设存储缓冲区将被写入存储围栏中的缓存或者是否需要重用该存储缓冲区条目,但我不知道存储缓冲区是否已分配给写入.
最终我要为自己回答的问题是,如果线程2有可能在一个相当复杂的应用程序中看到线程1的写入几秒钟而正在做其他工作.
1> Peter Cordes..:
记忆障碍,不要让其他线程看到你的店的任何更快。 (除了阻止以后的加载可以稍微减少提交缓冲存储的争用。)
存储缓冲区始终尝试尽快将已退休(已知的非推测性)存储提交到L1d高速缓存。由于MESI / MESIF / MOESI,这使它们在全球范围内可见。存储缓冲区没有设计为适当的高速缓存或写合并缓冲区(尽管它可以将背对背存储合并到同一高速缓存行),因此需要清空自身以为新存储腾出空间。与高速缓存不同,它希望保持自身为空而不是不满。
栅栏/屏障通过使当前线程等待而不是通过提高商店可见性来工作。
完全屏障(mfence
或lock
ed操作)的简单实现是使管线停止运行,直到存储缓冲区耗尽为止,但是高性能实现可以做得更好,并允许与内存顺序限制分开的无序执行。
(不幸的是,Skylake mfence
确实完全阻止了乱序执行,以修复晦涩的SKL079勘误,涉及从WC内存中的NT加载。但是lock add
,xchg
或者仅此而已,则只能阻止以后的加载读取L1d或存储缓冲区,直到屏障到达存储区的末尾。缓冲区。mfence
在较早的CPU上大概也没有这个问题。)
通常,在非x86架构(具有显式的asm指令以应对较弱的内存屏障,例如仅关注StoreStore篱笆而不关心负载)的原理是相同的:阻塞需要阻塞的任何操作,直到该核心完成了任何内容的早期操作类型。
有关:
全局不可见的加载指令讨论了加载变得全局可见的含义。
内存屏障是否可以确保高速缓存一致性已完成?
记忆屏障是否既充当标记又充当指示?
最终,我要为自己解答的问题是线程2是否有可能几秒钟看不到线程1的写入
不,最坏情况下的延迟可能类似于存储缓冲区长度(Skylake上的56个条目,从BDW中的42个条目)乘以高速缓存未命中延迟的时间,因为x86的强大内存模型(无StoreStore重新排序)要求存储按顺序提交。但是用于多个高速缓存行的RFO可以一次运行,因此最大延迟可能是其的1/5(保守估计:有10个行填充缓冲区)。在飞行中也可能存在来自负载的竞争,但是我们只需要一个数量级的包络数。
可以说,在3GHz CPU上,RFO延迟(DRAM或其他内核的延迟)为300个时钟周期(基本组成)。因此,商店变得全局可见的最坏情况下的延迟可能类似于300 * 56 / 5
= 3360核心时钟周期。因此,在一个数量级内,我们假设3GHz CPU的最坏情况约为1微秒。(CPU频率抵消了,因此以纳秒为单位的RFO延迟估计会更有用)。
那是您的所有商店都需要等待很长时间才能获得RFO的原因,因为它们都位于未缓存或由其他核心拥有的位置。而且它们都没有背对背地位于同一缓存行,因此没有一个可以合并到存储缓冲区中。因此,通常您希望它会更快。
我认为没有任何可行的机制可以花费一百微秒,更不用说一秒钟了。