- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Intel optimization manual讨论了处理器许多部分中存在的存储缓冲区的数量,但似乎没有讨论存储缓冲区的大小。是公共信息还是存储缓冲区的大小作为微体系结构细节保留?
我正在研究的处理器主要是Broadwell和Skylake,但是关于其他处理器的信息也将很好。
另外,存储缓冲区到底是做什么的?
最佳答案
相关:what is a store buffer?
How do the store buffer and Line Fill Buffer interact with each other?还很好地描述了执行存储指令的步骤以及该指令最终如何提交到L1d高速缓存。
整个存储缓冲区由多个条目组成。
每个内核都有自己的存储缓冲区1,以将执行和退出与提交到L1d缓存的过程分离开。即使是有序的CPU也可以从存储缓冲区中受益,避免在高速缓存未命中的存储中停顿,因为与负载不同,它们最终必须变得可见。 (没有实际的CPU使用顺序一致性内存模型,因此,即使在x86和SPARC-TSO中,至少也允许StoreLoad重新排序)。
对于推测性/乱序CPU,它还可以在检测到较旧指令中的异常或其他错误推测后回滚存储,而不必在全局范围内看到推测性存储。这显然对于正确性至关重要! (您不能回滚其他内核,因此,除非已知它们是非推测性的,否则您不能让它们看到您的商店数据。)
当两个逻辑内核都处于活动状态(超线程)时,Intel将存储缓冲区分为两个;每个逻辑核心得到一半。从一个逻辑核心加载仅监听其自身一半的存储缓冲区2。 What will be used for data exchange between threads are executing on one Core with HT?
存储缓冲区按照程序顺序(考虑到x86的强排序内存模型3),将已退休的存储指令中的数据尽快提交到L1d中。要求存储在退休时进行提交将不必要地使高速缓存未命中的存储停滞退休。仍在存储缓冲区中的退休存储肯定会发生并且无法回滚,因此它们实际上会损害中断延迟。 (从技术上讲,不需要中断就可以进行序列化,但是由IRQ处理程序完成的任何存储都必须等到现有挂起的存储被清空后才可见。并且iret
正在序列化,因此即使在最佳情况下,存储缓冲区也要在此之前被清空返回)。
这是一个常见的(?)误解,即必须显式刷新数据才能使数据对其他线程可见。内存屏障不会导致刷新存储缓冲区,完全的屏障会使当前内核等待直到存储缓冲区自身耗尽为止,然后再允许任何后续加载发生(即读取L1d)。原子RMW操作必须等待存储缓冲区耗尽后才能锁定高速缓存行,并在不使其保持MESI Modified状态的状态下进行加载和存储到该行,从而阻止系统中的任何其他代理在观察期间原子操作。
为了实现x86的有序内存模型,同时仍以微体系结构方式允许早期/无序加载(以及在体系结构允许发生加载时稍后检查数据是否仍然有效),加载缓冲区+存储缓冲区条目共同构成了内存顺序缓冲区(MOB)。 (如果允许加载时仍不存在高速缓存行,则可能是内存顺序的错误推测。)这种结构大概是mfence
和lock
指令可以放置障碍来阻止StoreLoad重新排序的原因。不会阻止乱序执行。 (尽管mfence
on Skylake does block OoO exec of independent ALU instructions,作为实现细节。)movnt
绕过高速缓存的存储区(例如movntps
)也将通过存储缓冲区,因此它们可以被视为推测性的,就像OoO exec CPU中的其他所有内容一样。但是它们直接提交给LFB(行填充缓冲区)(又名写合并缓冲区),而不是L1d高速缓存。
英特尔CPU上的存储指令解码为存储地址和存储数据uops(微融合为一个融合域uop)。 store-address uop只是将地址(可能还有存储宽度)写入到存储缓冲区中,因此以后的加载可以设置store-> load转发或检测到它们没有重叠。存储数据uop写入数据。
存储地址和存储数据可以按任意顺序执行,以先准备好的顺序为准:分配/重命名阶段将前端的uops写入ROB,后端的RS也为该负载分配负载或存储缓冲区。在发行时存储uops。或拖延直到有空。由于分配和提交是按顺序进行的,这可能意味着较早/较年轻的人很容易跟踪,因为它可以只是循环缓冲区,而不必担心旧的长寿命条目在回绕后仍在使用。 (除非绕过缓存/无序的NT存储可以做到这一点?它们可以不按顺序提交给LFB(行填充缓冲区)。与普通存储不同,它们直接提交给LFB进行内核外传输,而不是L1d )
但是条目的大小是多少?
存储缓冲区的大小是按条目而不是位进行度量的。
狭窄的存储区不会在存储区缓冲区中“使用较少的空间”,它们仍然只使用1个条目。
Skylake的存储缓冲区有56个条目(wikichip),而Haswell / Broadwell中只有42个条目,而SnB / IvB中有36个条目(David Kanter's HSW writeup on RealWorldTech has diagrams)。您可以在Kanter在RWT或Wikichip的图表中找到最新x86 uarches的编号,或其他各种来源。
SKL / BDW / HSW还具有72个加载缓冲区条目,SnB / IvB具有64个加载缓冲区条目。这是未执行或正在等待数据从外部缓存到达的运行中加载指令的数量。
每个条目的位大小是一个实现细节,对优化软件的方式几乎没有影响。同样,我们不知道uop的大小(在前端,在ROB中,在RS中),TLB实现细节或许多其他内容,但是我们确实知道有多少ROB和RS有多少个条目,以及各个uarch中有多少个不同类型的TLB条目。
英特尔不会发布其CPU设计的电路图,而且这些尺寸通常也不为人所知(AFAIK),因此我们甚至无法满足我们对设计细节/折衷的好奇心。
在存储缓冲区中写入合并:
在提交之前,可以(也可能在存储缓冲区中合并)到同一高速缓存行的背对背窄存储,也可以合并在一起,因此可以只花一个周期在L1d高速缓存的写端口上提交多个存储。
我们肯定知道某些非x86 CPU会执行此操作,并且我们有一些证据/理由怀疑Intel CPU可能会执行此操作。但是,如果发生这种情况,那就是有限的。 @BeeOnRope和我目前认为英特尔CPU可能没有进行任何重大合并。如果这样做,最合理的情况是,所有都进入同一高速缓存行的存储缓冲区末尾的条目(准备提交到L1d)可能会合并到一个缓冲区中,如果我们正在等待RFO,则会优化提交该缓存行。参见有关Are two store buffer entries needed for split line/page stores on recent Intel?的评论中的讨论。我提出了一些可能的实验,但还没有完成。
关于可能的存储缓冲区合并的早期内容:
请参阅以以下评论开头的讨论:Are write-combining buffers used for normal writes to WB memory regions on Intel?
而且Unexpectedly poor and weirdly bimodal performance for store loop on Intel Skylake可能是相关的。
我们可以肯定地知道一些弱排序的ISA(例如Alpha 21264)确实在其存储缓冲区中存储了合并,因为the manual documents it以及它在每个周期可以提交和/或从L1d读取内容的限制。在文档中,PowerPC RS64-II和RS64-III的详细信息也较少,链接来自此处的注释:Are there any modern CPUs where a cached byte store is actually slower than a word store?
人们已经发表了有关如何在TSO内存模型(例如x86)中存储合并的论文(更具侵略性)。 Non-Speculative Store Coalescing in Total Store Order
如果将其数据复制到同一行中的存储,则合并可以允许在其数据提交到L1d之前释放存储缓冲区条目(大概仅在退出之后)。仅当没有其他行的存储将它们分开时,才会发生这种情况,否则,它将导致存储以程序顺序的方式提交(成为全局可见的),从而违反了内存模型。但是我们认为这可能发生在同一行的任何两个存储中,甚至是第一个和最后一个字节。
这个想法的问题是,SB条目分配可能是一个环形缓冲区,例如ROB。不按顺序发布条目将意味着硬件将需要扫描每个条目以找到空闲的条目,然后,如果它们按不正确的顺序重新分配,则它们在以后的存储中不会处于程序顺序。这会使分配和存储转发变得更加困难,因此这似乎不可行。
正如在
Are two store buffer entries needed for split line/page stores on recent Intel?,即使一个SB条目跨越了一个缓存行边界,它也应该拥有一个存储的所有存储。在离开SB时提交到L1d缓存时,缓存行边界变得很重要。我们知道,存储转发可用于跨缓存行拆分的存储。如果将它们在存储端口中拆分为多个SB条目,则似乎不太可能。
术语:我一直在使用“推销”来谈论在存储缓冲区中的合并,而“写合并”则是在谈论(有希望)在没有RFO的情况下进行全行写入之前在LFB中合并的NT存储。或将执行相同操作的存储到WC内存区域。
这种区别/约定只是我所做的。根据评论中的讨论,这可能不是标准的计算机体系结构术语。
英特尔的手册(尤其是优化手册)是由不同的作者多年编写的,并且在术语上也不一致。仔细阅读优化手册的大部分内容,尤其是在谈到Pentium4时。关于Sandybridge和Haswell的新部分是可靠的,但较旧的部分可能只提供过时的建议,而该建议仅/主要与P4相关(例如inc vs. add 1),或者某些优化规则的微体系结构解释可能令人困惑/错误。特别是第3.6.10节“写合并”。由于内存排序规则,关于使用LFB组合存储同时等待行到达高速缓存未命中的存储到WB内存的第一个要点似乎是不合理的。参见上面我和BeeOnRope之间的讨论,以及此处的评论。
脚注1:
写合并高速缓存以缓冲内部高速缓存的回写(或直写)将具有不同的名称。例如推土机系列使用16k直写式L1d高速缓存和一个4k的小写回缓冲区。 (有关详细信息和更多详细信息,请参见Why do L1 and L2 Cache waste space saving the same data?。有关在Bulldozer系列CPU上放慢到4k以上的重写数组微基准,请参见Cache size estimation on your system?。)
脚注2:某些POWER CPU允许其他SMT线程在存储缓冲区中监听已退休的存储:这可能导致不同的线程与其他线程就存储的全局顺序产生分歧。 Will two atomic writes to different locations in different threads always be seen in the same order by other threads?
脚注3:内存模型较弱的非x86 CPU可以按任何顺序提交已淘汰的存储,从而可以更积极地将多个存储合并到同一行,并使高速缓存未命中存储不会使其他存储停止提交。
关于performance - 英特尔硬件上的存储缓冲区大小?什么是存储缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54876208/
我刚刚意识到二进制编译器会将源代码转换为目标平台的二进制文件。有点明显...但如果编译器以这种方式工作,那么同一个编译器如何用于不同的系统,如 x86、ARM、MIPS 等? 难道他们不应该“知道”硬
在我的 SDL 游戏中,出于游戏玩法和性能原因,我希望保留固定的游戏区域分辨率。 我想做的是有一个小分辨率(例如 320 * 240),并且在调整窗口大小时/切换到全屏模式时让 SDL/显卡缩放每个像
我正在使用这些方法来激活 SurFaceView 上的触摸焦点 private SurfaceView surfaceiew; private CameraSource camSource; priv
您好,当我从硬件菜单更改设备时,我遇到了这个奇怪的问题,但我想我可能遗漏了一些简单的东西。 我的 View Controller 中有这段代码: - (void)touchesBegan:(NSSet
编写一个名为 weird() 的函数,它将三个字符串作为参数并向后打印最长的一个。 (在平局的情况下,应该选择较早的参数字符串。 函数调用: weird("I", "Love", "Python")
您好,我正在尝试设置 hadoop 环境。简而言之,我要解决的问题涉及数十亿个大小为几 MB 的 XML 文件,使用 HIVE 从中提取相关信息,并对这些信息进行一些分析工作。我知道这在 hadoop
我知道 Phidgets,但是,我正在寻找可以与 C# 接口(interface)的一些其他类型的硬件。 谁有好东西? 最佳答案 查看 Netduino .它基于 Arduino,但使用 .Net
说一个函数(例如模乘法、正弦函数)是在硬件而不是软件中实现是什么意思? 最佳答案 在硬件中实现意味着电路(通过逻辑门等)可以执行操作。 例如,在 ALU 中,处理器在物理上能够将一个字节加到另一个字节
我需要编写一个程序,在可能状态的大空间中执行并行搜索,在此过程中发现了新区域(并开始了他们的探索),并且由于在其他地方获得的中间结果消除了可能性,因此提前终止了对某些区域的探索在其中发现新的有用结果。
我们需要通过带有硬件 token 的 EV 代码对 InstallShield 2013 Express 的安装进行签名,但是无法导出私钥证书文件,因此唯一的方法是使用 DigiCertUtil 工具
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 2 年前。 Improve this ques
我考虑从库中丢弃处理大端情况的代码,如果平台不是小端,则在初始化期间简单地抛出一个异常。如果我们限制为,我无法想象会有任何大端硬件 托管任何网站的典型服务器硬件 服务器根据开放计算项目规范 所有常见的
我知道这可以做到,但找不到交换目标调试设备的地方。我现在正在使用模拟器,但想切换到设备,反之亦然。谁能指出我正确的方向? 谢谢。 最佳答案 像这样.. 右键单击 PROJECT--->Run As--
我正在尝试创建一个监听音量键事件的服务。 每当按下音量键时,服务应向号码发送短信,但我无法检测到音量键事件。 最佳答案 您可以使用 OnKeyListener可以检测按键事件(包括音量键)。您可以找到
谁能解释一下中断如何从最低层(硬件)传递到应用程序。 所以在下图中我知道处理器之后发生了什么。 但是我想要从键盘按下到处理器的中断过程在硬件中发生了什么,例如它如何传递扫描代码,中断 Controll
我的任务是构建一个应用程序,其中业务用户将定义一些数据操作和处理规则(例如,取一个数值并将其平均分配给根据中指定的条件选择的多个记录)规则)。 每月必须运行一个批处理应用程序,以便根据定义的规则处理大
所以这是我的愚蠢问题: PGP/GPGP可以用来对文本进行签名,其他的使用公钥来验证。 比方说,非对称密码算法处理空间。 有没有什么算法可以处理时间? 例如在 2011-10-10 10:10:10
使用 nvcc 编译 CUDA 程序是否需要安装支持 CUDA 的显卡(在 Linux 中)?或者可以在任何地方编译程序并且只能在这样的系统上运行? 最佳答案 不,编译不需要显卡。 您甚至不需要一个来
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我有一个奇怪的问题,但我对这个话题很感兴趣。 是否有可能直接访问当前基于 x64 的计算机的硬件,而无需使用某种 HAL(硬件抽象层)或其他操作系统(udev、upower 等)的附属物?我不是在谈论
我是一名优秀的程序员,十分优秀!