gpt4 book ai didi

performance - 如果寄存器如此之快,为什么我们没有更多的寄存器?

转载 作者:行者123 更新时间:2023-12-01 23:13:17 25 4
gpt4 key购买 nike

在 32 位中,我们有 8 个“通用”寄存器。对于 64 位,数量翻了一番,但它似乎与 64 位变化本身无关。
现在,如果寄存器如此之快(没有内存访问),为什么不自然地有更多的寄存器? CPU 制造商不应该将尽可能多的寄存器工作到 CPU 中吗?为什么我们只有我们拥有的数量的逻辑限制是什么?

最佳答案

没有大量寄存器的原因有很多:

  • 它们与大多数管道阶段高度相关。首先,您需要跟踪他们的生命周期,并将结果转发回之前的阶段。复杂性很快变得难以处理,并且所涉及的电线数量(字面意思)以相同的速度增长。它在面积上很昂贵,这最终意味着在某一点之后它在功率、价格和性能上很昂贵。
  • 它占用指令编码空间。 16 个寄存器占用 4 位用于源和目标,如果您有 3 操作数指令(例如 ARM),则另外 4 位。仅仅为了指定寄存器就占用了大量的指令集编码空间。这最终会影响解码、代码大小和复杂性。
  • 有更好的方法可以达到相同的结果...

  • 现在我们确实有很多寄存器——它们只是没有明确编程。我们有“注册重命名”。虽然您只能访问一个小集合(8-32 个寄存器),但它们实际上是由一个更大的集合(例如 64-256)支持的。然后 CPU 跟踪每个寄存器的可见性,并将它们分配给重命名的集合。例如,您可以连续多次加载、修改然后存储到寄存器中,并根据缓存未命中等实际独立执行这些操作中的每一个。 在 ARM 中:
    ldr r0, [r4]
    add r0, r0, #1
    str r0, [r4]
    ldr r0, [r5]
    add r0, r0, #1
    str r0, [r5]

    Cortex A9 内核会进行寄存器重命名,因此对“r0”的第一次加载实际上是进入重命名的虚拟寄存器——我们称之为“v0”。加载、增量和存储发生在“v0”上。同时,我们还再次对 r0 执行加载/修改/存储,但这将被重命名为“v1”,因为这是一个使用 r0 的完全独立的序列。假设从“r4”中的指针加载由于缓存未命中而停止。没关系 - 我们不需要等待“r0”准备就绪。因为它被重命名,我们可以使用“v1”(也映射到 r0)运行下一个序列——也许这是一个缓存命中,我们刚刚获得了巨大的性能胜利。
    ldr v0, [v2]
    add v0, v0, #1
    str v0, [v2]
    ldr v1, [v3]
    add v1, v1, #1
    str v1, [v3]

    我认为 x86 近来有大量重命名的寄存器(大概 256 个)。这意味着每条指令都有 8 位乘以 2,只是为了说明源和目标是什么。这将大大增加整个核心所需的电线数量及其大小。因此,大多数设计人员已经解决了大约 16-32 个寄存器的最佳位置,对于无序 CPU 设计,寄存器重命名是缓解它的方法。

    编辑 : 乱序执行和寄存器重命名的重要性就在于此。一旦你有了 OOO,寄存器的数量就没有那么重要了,因为它们只是“临时标签”并被重命名为更大的虚拟寄存器集。您不希望数字太小,因为很难编写小的代码序列。这对于 x86-32 来说是一个问题,因为有限的 8 个寄存器意味着很多临时文件最终会通过堆栈,并且核心需要额外的逻辑来将读/写转发到内存。如果您没有 OOO,您通常谈论的是小内核,在这种情况下,大寄存器集的成本/性能优势很差。

    因此,对于大多数类型的 CPU,寄存器组大小有一个自然的最佳位置,最大约为 32 个架构寄存器。 x86-32 有 8 个寄存器,它绝对太小了。 ARM 使用了 16 个寄存器,这是一个很好的折衷方案。如果有的话,32 个寄存器有点太多了——你最终不需要最后 10 个左右。

    这些都没有涉及您为 SSE 和其他向量浮点协处理器获得的额外寄存器。这些作为额外的集合是有意义的,因为它们独立于整数核心运行,并且不会以指数方式增加 CPU 的复杂性。

    关于performance - 如果寄存器如此之快,为什么我们没有更多的寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6079215/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com