基于寄存器的体系结构比堆栈体系结构快多少?

时间:2010-03-11 16:24:38

标签: compiler-construction

学习编译器课程,我想知道为什么要使用寄存器。 通常情况下,呼叫者或被呼叫者必须保存寄存器值,然后恢复

在某种程度上,他们总是最终使用堆栈。使用寄存器真的值得创造额外的复杂性吗?

请原谅我的无知。

更新:请知道,寄存器比RAM和其他类型的缓存更快。我主要担心的是,必须“保存”寄存器中的值,然后将其“恢复”到寄存器中。在这两种情况下,我们都在访问某种缓存。首先使用缓存不是更好吗?

7 个答案:

答案 0 :(得分:8)

在速度/延迟层次结构中,寄存器最快(通常为零周期延迟),L1缓存是下一个(通常是1个或更多个延迟周期),然后在此之后迅速下降。因此,通常寄存器访问是“免费的”,而内存访问总是涉及一些成本,即使缓存该访问也是如此。

保存和恢复寄存器通常只发生在(a)函数调用或上下文切换的开始/结束时,或(b)当编译器用完临时变量的寄存器并需要“溢出”一个或多个寄存器时回到记忆中。通常,优化良好的代码会将大多数频繁访问的(“热”)变量保留在寄存器中,至少在函数的最内层循环中。

答案 1 :(得分:2)

我说这对编译器来说不是一个问题,因为它与CPU有关。编译器必须使用目标体系结构。

以下是其他答案所掩盖的内容:它取决于实际电路级别的CPU架构。机器指令归结为从某处获取数据,修改数据,加载或转到下一条指令。

类比

想想问题就像木工为你修建或修理椅子一样。他的问题将是“椅子在哪里”,以及“椅子需要做什么”。他或许可以在你的房子里修理它,或者他可能需要把椅子带回他的商店去做。无论哪种方式都可行,但取决于他是如何准备在固定地点以外工作的。它可能会减慢他的速度,也可能是他的专长。

现在,回到CPU。

说明

无论CPU有多么并行,例如具有多个加法器或指令解码流水线,这些电路都位于芯片上的特定位置,并且数据必须加载到可以执行操作的位置。该程序负责将数据移入和移出这些位置。在基于堆栈的机器中,它可能提供直接修改数据的指令,但它可能在微代码中进行内务处理。无论数据来自堆栈还是来自堆,加法器都以相同的方式工作。不同之处在于程序员可用的编程模型。寄存器基本上是处理数据的定义位置。

答案 2 :(得分:2)

嗯,似乎答案也是在书中(java中的现代编译器实现)。 这本书提出了4个答案:

  1. 某些程序不会调用其他程序。如果你绘制过程调用图,并假设每个过程平均调用1-2个其他过程,你会得到一个树,其中“leafs”(不调用其他的过程)超过树非 - 左节点。所以你赢了那条路。有些编译器根本没有为这些叶节点分配堆栈帧。
  2. 一些优化编译器使用“过程间寄存器分配” - 这基本上意味着它们会分析您的所有源代码,并采用智能方式将参数提前存储到过程中,从而最大限度地减少写入堆栈。
  3. 在调用另一个函数之前,某些过程是使用变量完成的 - 在这种情况下,该寄存器可以被覆盖。
  4. 有些架构使用“注册窗口”,因此每个函数调用都可以分配新的寄存器集,而不需要内存流量。

答案 3 :(得分:1)

在延迟和带宽方面,访问RAM通常比访问寄存器慢得多。有些CPU具有有限大小的硬件堆栈 - 这允许将寄存器推送到堆栈并将其弹回 - 但它们仍然直接使用寄存器进行计算。使用纯堆栈机器(其中有许多学术示例)也很困难,增加了更多的复杂性。

答案 4 :(得分:1)

基于堆栈和寄存器的计算机之间的区别是模糊的。许多现代注册机使用寄存器重命名来隐藏堆栈,只在内部寄存器耗尽时才将数据转储到实际堆栈。一些旧的堆栈机器做了类似的事情,将几个指令和窥视孔流水线化,将push-modify-pop序列优化为就地修改。

现代CPU使用花式并行执行指令的方式,堆栈与寄存器机器之间可能没有太大区别。寄存器机器可能略有优势,因为编译器可以提供有关数据重用的更好提示,但如果英特尔不愿意设计一个,那么十亿美元的Lisp堆栈机器将会非常快速。

答案 5 :(得分:1)

我相信你在问为什么要使用寄存器,因为无论如何变量最终会进入堆栈。

答案是,将寄存器视为堆栈顶部前5或6(或其他)项目的缓存。如果堆栈的顶部被访问的次数远多于底部(在许多程序中都是如此),那么拥有这个缓存会加快速度。

我想你可以说为什么有用户可见的寄存器,而不是前几位的透明缓存。我不确定,但我怀疑让编译器知道将缓存哪些值可以让它更多地优化存储分配。毕竟,如果堆栈中存在一些截止,之后变量访问将会更加昂贵,那么您可以安排变量来处理它。

答案 6 :(得分:0)

它可以产生巨大的变化。我曾经指导PowerPC / Macintosh上的编译器将正确的局部变量放入寄存器中,并使应用程序的主要处理任务加速了2倍。该任务基本上是CPU绑定的,但通过使用寄存器消除了内存访问,提高了2倍的速度。在其他情况下,加速可能会更加激烈。

这是一个叶子功能。它没有调用其他功能。