处理器在等待获取主内存时会做什么?


26

假设l1和l2高速缓存请求导致未命中,处理器是否会停滞直到访问主存储器?

我听说过切换到另一个线程的想法,如果可以的话,用来唤醒停滞线程的原因是什么?


4
你做了什么研究?这当然是可用的信息。我将留给专家回答,但是我认为线程切换不是一件有用的事情。通常,在CPU上切换上下文会引起许多内存访问(因此可能导致高速缓存未命中)。有一些措施,例如操作重新排序(利用管道),但是停滞似乎别无选择。
拉斐尔

@Raphael我主要阅读的是计算机体系结构书籍,Steve Furber的ARM片上系统体系结构可能是我所阅读的最全面的书籍。但是,我已经开始阅读《计算机体系结构:一种定量方法》。它讨论了避免诸如线程切换,OOE和乱序内存操作之类的停顿技术,尽管它并没有真正说明现代设计的复杂性,就像大多数教科书一样,它们涵盖了较旧的体系结构或对这些东西的含义给出了模糊的建议。实施并共同努力。
102948239408 2014年

在我的问题上扩展,高速缓存似乎具有较小的延迟,并且在响应中具有确定性,但是如果遇到最坏的情况,通过分页表检索物理地址,则可以完成数千条指令,其中一些指令是从ILP提取的同一线程中完成的。处理器上发生什么硬件交互,以决定可以调度另一个线程,如果发生这种情况,则使用什么通信方式唤醒该线程。更进一步,如果OoOE是否有一种在切换线程时处理完整结果队列的技术?
102948239408 2014年

1
从您的问题中不清楚您是否对现代CPU的细节感兴趣。这不仅可能是题外话,也可能是专有信息。有了这些概念,我们可以为您提供帮助;在过去的几十年中,这些更改的实现程度可能比实现方式的更改少。关于您的问题,请结合您所知道的知识,并提出一个具体的概念性(或参考要求)问题。
拉斐尔

1
我已经回答了有关一般概念的问题,但是从您的评论来看,您可能会考虑更高级的考虑。但是,如果您需要更高级的答案,则需要针对特定​​的体系结构和技术类型使问题更具体。
吉尔(Gilles)'所以

Answers:


28

内存延迟是计算机体系结构研究中研究的基本问题之一。

投机执行

带有乱序指令问题的推测执行通常能够找到有用的工作来填补L1缓存命中期间的等待时间,但通常在10或20个周期左右后就耗尽了有用的工作。已经进行了一些尝试来增加长时间等待未命中期间可以完成的工作量。一种想法是尝试进行价值预测(Lipasti,Wilkerson和Shen,(ASPLOS-VII):138-147,1996)。这种想法在学术建筑研究界很流行了一段时间,但似乎在实践中不起作用。从历史上的垃圾箱保存值预测的最后一次尝试是超前执行(Mutlu,Stark,Wilkerson和Patt(HPCA-9):129,2003年)。在超前执行中,您意识到您的价值预测将是错误的,但无论如何都要进行推测性执行,然后根据该预测丢弃所有工作,并根据理论,您至少将对L2缓存进行一些预取错过。事实证明,冒名顶替浪费了太多能量,这是不值得的。

在这种情况下,可能会在业界引起一定关注的一种最终方法涉及创建非常长的重新排序缓冲区。指令是根据分支预测进行推测性执行的,但不会进行值预测。取而代之的是,所有依赖于长等待时间加载的指令都会在重新排序缓冲区中等待。但是,由于重排序缓冲区很大,因此如果分支预测变量执行得体,您可以继续获取指令有时您将可以在指令流的后面找到有用的工作。该领域的一项有影响力的研究论文是连续流管道(Srinivasan,Rajwar,Akkary,Gandhi和Upton(ASPLOS-XI):107-119,2004年)。(尽管作者全部来自英特尔,但我相信这个想法在AMD上获得了更多关注。)

多线程

使用多个线程来进行延迟容忍已有很长的历史,在业界取得了更大的成功。所有成功的版本都使用硬件支持多线程。最简单(也是最成功的)版本就是通常所说的FGMT(细粒度多线程)或交错多线程。每个硬件内核都支持多个线程上下文(上下文本质上是寄存器状态,包括诸如指令指针之类的寄存器和任何隐式标志寄存器)。在细粒度的多线程处理器中,每个线程都-订购。处理器跟踪哪些线程在长时延加载未命中时停滞,哪些线程准备好执行下一条指令,并且在每个周期上使用简单的FIFO调度策略选择执行该周期的就绪线程。大规模的早期示例是Burton Smith的HEP处理器(Burton Smith继续设计Tera超级计算机,它也是一种细粒度的多线程处理器)。但是我认为这个想法可以追溯到1960年代。

FGMT对流工作负载特别有效。所有现代GPU(图形处理单元)都是多核,其中每个核都是FGMT,该概念也广泛用于其他计算领域。Sun的T1也是多核FMGT,英特尔的Xeon Phi(该处理器通常仍称为“ MIC”,以前称为“ Larabee”)也是如此。

的想法同时多线程(Tullsen,埃格斯,和Levy),(ISCA-22:392-403,1995)相结合的硬件多线程与推测执行。处理器具有多个线程上下文,但是每个线程都是推测性执行的,并且无序执行。然后,更复杂的调度程序可以使用各种启发式方法从最有可能从事有用工作的线程中获取(Malik,Agarwal,Dhar和Frank,(HPCA-14:50-61),2008)。某大型半导体公司开始使用术语“ 超线程”来实现同时多线程,而该名称似乎是当今使用最广泛的名称。

低层次的微架构问题

重新阅读您的评论后,我意识到您也对处理器和内存之间发生的信号传递也很感兴趣。现代缓存通常允许同时处理多个未命中事件。这称为无锁缓存(Kroft,(ISCA-8):81-87,1981)。(但是该论文很难在网上找到,而且有点难以阅读。简短的回答:有很多簿记,但是您只是处理它。硬件簿记结构称为MSHR(丢失信息/状态保存寄存器) ),这就是Kroft在1981年的论文中给它起的名字。)


非常感谢您提供全面的答案,我将尝试研究无锁缓存。我措辞不好的问题确实是要确认处理器在主存储器访问期间是否确实会继续加载和存储,以及使用了哪些微体系结构技术来做到这一点。
102948239408 2014年

+1,1.如果不使用循环调度,真的是桶处理吗?维基百科使它成为FGMT的同义词。(我可以接受通过跳过将“桶形处理器”应用于循环程序,尽管这会打破类比,因为缺少梯级(参见未就绪的线程)不会使桶的圆周收缩。(我认为“真”桶形处理器是?稀土也许是CDC 6600外设处理器-因为他们浪费了一个周期,但它确实简化了硬件)2. SoEMT一提像安腾的超线程和IBM的北极星等人似乎特别适合给定的问题。
保罗A.克莱顿2014年

@ 102948239408,您可能会在Google上搜索的另一件事是诸如“命中小姐”和“错过下小姐”之类的术语(另一个选项是“失速下小姐”,但我只是尝试过,似乎没有任何用处。) (某些)架构师当前使用的术语,用于缓存可能允许的内容的不同选项。
Wandering Logic

@ PaulA.Clayton,术语绝对不是我的强项。我同意你的看法,即桶加工应该是循环式的。但是我想不出任何其他含义,那就是:一堆又一堆的有序线程的逐周期交织(GPU,Xeon Phi和Sun T1都是这样做的)。是FGMT吗?我一直认为FGMT包括SMT(即,不指定必须按顺序执行线程),但是在这种情况下FGMT可能比“桶式处理器”更好?
Wandering Logic

Wikipedia的Barrel处理器文章指出:“也称为“交织”或“细粒度”时间多线程”,因此IMT和FGMT至少是公认的术语。我想我读的是“细粒度”而不是“交错”,但是交错并不罕见。我通常使用FG(对我而言,“粒化”意味着比SMT提供的分离更多);FG的优势是交错可应用于SoEMT。我怀疑这只是“桶式处理器”用法的一种变化,我将不得不咧嘴笑着忍受。
保罗·克莱顿

16

简短的答案是:没有,处理器停顿。

没有太多的可能性。切换到其他任务实际上并不是一个选择,原因有两个。这是一项昂贵的操作,并且由于当前任务和其他任务正在争用缓存中的空间,因此切换到其他任务本身可能需要主存储器访问,因此可能切换回原始任务。此外,这将必须涉及操作系统,因此处理器将必须触发某种形式的中断陷阱 -实际上,处理器将切换至某些内核代码。

当处理器停止运行时,计时器继续运行,因此可能会有计时器中断,也可能有其他外设的中断。因此,与在高速缓存访​​问期间相比,上下文切换更有可能在主存储器访问期间发生,但这仅仅是因为它需要更长的时间。

尽管如此,现代计算机的确包含了多种技术,以减少处理器等待主内存所浪费的时间。停转确实会发生,但只有在无法避免的情况下才会发生。

一种技术是推测性获取:处理器尝试猜测将访问哪个内存位置,并获取它以提前缓存。例如,内存块上的循环很常见,因此,如果已为内存地址0x12340000、0x12340010和0x12340020加载了缓存行,则为0x12340030加载行可能是一个好主意。编译器可以通过生成预取指令来提供帮助,这些预取指令类似于加载,只是它们仅将数据从主存储器传输到缓存,而不传输到处理器寄存器。

另一种技术是投机执行。在执行加载之前,处理器开始执行下一条指令。由于指令的流水线化,这自然会发生。只有不依赖于加载值的指令才能通过这种方式执行:处理器必须执行依赖关系分析。对于条件指令(例如,负载r1;如果r1≠0,则分支),处理器采用分支预测试探法来猜测该值是多少。如果负载触发中止,可能需要重新考虑负载之后的推测执行。

诸如Itanium之类的某些体系结构通过默认情况下允许对指令进行重新排序来促进以方便的顺序执行指令:程序由非常长的指令字组成,而不是由一系列语义上依次执行的基本指令组成:单个指令包括许多操作将由处理器的不同组件并行执行。

切换到另一个线程发生在高端x86处理器上的超线程中。这是一种硬件设计技术:每个处理器内核包含两个单独的寄存器组(每个寄存器组对应于一个任务上下文),但是包含其他元素的单个实例,因此它可以支持两个独立的执行线程,但只能有效地从一个执行指令一个时间。当一个线程停止时,另一线程继续。从软件的角度来看,有两个独立的处理器。碰巧这些处理器在后台共享许多组件。

交换是内存高速缓存层次结构中的又一层:主内存可以看作是交换空间的高速缓存。通过交换,机制和性能比是不同的。如果任务需要通过交换加载数据,则加载指令将触发陷阱,该陷阱将执行内核代码以在RAM中分配页面并从磁盘加载其内容。发生这种情况时,内核可能会决定切换到另一个任务。


与第一段和倒数第二段相反,“技巧”是超线程不需要发生真正的上下文切换,对吗?CPU同时完全维护两个上下文。
拉斐尔

1
@Raphael对:就软件而言,除了性能外,还有两个CPU。
吉尔(Gilles)'所以

超线程CPU具有许多半独立的执行单元(整数和浮点加法器,乘法器等),我认为两个上下文都可以同时使用单独的执行单元,尽管不是100%可以肯定。
罗素·博罗戈夫

@RussellBorogove是的,我没有提到它,因为即使非超线程CPU可以有多个ALU / FPU / ...反之独立内核有时共享FPU等
吉尔“SO-停止作恶”

5

该问题的答案将随所讨论的体系结构而异。尽管许多CPU会因为切换线程花费的时间太长而停顿(ARM,没有超线程的x86等),但这并不是每种体系结构都采用的方法。在某些体系结构中,在CPU上调度的每个线程都有其自己的独立寄存器文件,因此处理器可以简单地从不等待内存访问的线程执行工作。据我了解,这在一定程度上是x86超线程的功能(仅使用2个线程),但是在GPGPU上它更为常见建筑。在CUDA的特定情况下,通常会在任何给定时间将至少几十个(即使不是数百个)线程扭曲加载到给定的多处理器上,每个线程(数百个或数千个)都有自己的寄存器。当给定线程发出内存访问时,这允许体系结构在下一个周期从另一个线程执行指令。因此,只要加载了足够多的线程,处理器核心就永远不会为内存访问而空闲。有关更多信息,请参见性能准则内存层次结构

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.