深入解读SiFiveP550的微架构内部

360影视 2025-01-27 22:17 2

摘要:RISC-V 是一个相对年轻的开源指令集。到目前为止,它已经在微控制器和学术应用中获得了关注。例如,Nvidia 用基于 RISC-V 的微控制器取代了其 GPU 中的 Falcon 微控制器。许多大学项目也使用了 RISC-V,例如伯克利的BOOM 。

RISC-V 是一个相对年轻的开源指令集。到目前为止,它已经在微控制器和学术应用中获得了关注。例如,Nvidia 用基于 RISC-V 的微控制器取代了其 GPU 中的 Falcon 微控制器。许多大学项目也使用了 RISC-V,例如伯克利的BOOM 。

然而,将 RISC-V 转移到更易于消费者看到、性能更高的应用程序中将是一个艰巨的过程。SiFive 在推动 RISC-V CPU 实现更高性能目标方面发挥着关键作用,其地位与 Arm(该公司)相似。Arm 和 SiFive 都设计并授权 IP 块。创建完整芯片的任务留给了实施者。

通过设计 CPU 模块,SiFive 和 Arm 都可以降低在各自的 ISA 生态系统中构建更高性能设计的入门成本。但要在 RISC-V 生态系统中实现这一点,SiFive 需要开发强大的 CPU 内核。在这里,我将介绍 SiFive 的 P550。该内核的目标是“在不到同类 Arm Cortex A75 一半的面积上实现 30% 的性能提升”。

与 Arm 的内核一样,P550 的性能在很大程度上取决于其实现方式。在本文中,我测试了 Eswin EC7700X SoC 中实现的 P550。这款 SoC 具有 1.4 GHz 四核 P550 集群,具有 4 MB 共享缓存。EIC7700X 采用台积电的 12nm FFC 工艺制造。承载 SoC 的 SiFive Premier P550 开发板具有 16 GB 的 LPDDR5-6400 内存。为了便于理解,我收集了一些来自 Pixel 3a 中的 Qualcomm Snapdragon 670 的比较数据。Snapdragon 670 具有以 2 GHz 运行的双核 Arm Cortex A75 集群。

概述

P550 是一个 3 宽无序核心,具有 13 级流水线。无序执行使核心能够越过停滞的指令来提取指令级并行性。这对于实现高性能至关重要,因为缓存和内存延迟可能是现代 CPU 的重要限制因素。P550 远非 SiFive 的第一个无序设计。这一区别属于 SiFive 的 U87,它也是一种 3 宽无序设计。P550 几年后问世,应该更加成熟。

Arm 的 Cortex A75 也是一个 3 宽的无序核心。它是 Arm Cortex A73 的改进版本,并继承了无序退出等独特功能。Anandtech表示 A75 拥有 11-13 级流水线,但他们的图表表明最低错误预测惩罚可能接近 11 个周期。

与 SiFive 的 P550 一样,Arm Cortex A75 拥有适度大小的乱序执行引擎。两者与当今英特尔和 AMD 的高性能设计相差甚远,并且针对低功耗和面积进行了优化。

分支预测

快速准确的分支预测对于性能和能效都至关重要。SiFive 为 P550 提供了 9.1 KiB 的分支历史表,这有助于核心将过去的分支行为与分支结果关联起来。从抽象测试来看,在越来越长的随机模式中,采用/不采用各种数量的分支,P550 的分支预测器似乎具有相当好的模式识别能力。它远远达不到高性能核心的水平,但这是意料之中的。

与 Arm 的 Cortex A75 相比,P550 可以处理少量分支的较长模式。不过,随着更多分支的加入,差距会缩小。

分支预测器的速度也很重要,尤其是在具有大量分支的高 IPC 代码中。P550 似乎有一个 32 条目 BTB,能够处理没有气泡的分支。除此之外,只要测试适合 32 KB,内核就可以每三个周期处理一次分支。很可能,P550 没有另一个 BTB 级别。如果分支错过了 32 条目 BTB,内核只需在分支到达前端时计算分支的目标地址。如果是这样,P550 的 32 KB L1 指令缓存有 3 个周期的延迟。

Arm 的 Cortex A75 也使用看似单个小型 BTB 级别。两个内核都缺少高性能内核通常具有的大型解耦 BTB。

P550 使用 16 个条目的返回堆栈来预测函数调用的返回。A75 似乎有一个包含 42 个条目的返回堆栈,因为每个调用+返回对的延迟在我超过该值之前不会达到拐点。即使使用更大的返回堆栈,A75 更高的 2 GHz 时钟速度也使其在返回堆栈命中的常见情况下实现类似的性能。

当超出返回堆栈容量时,P550 的延迟会急剧上升。这与 A75 的延迟增长较为温和形成鲜明对比。也许 A75 只会对被推出堆栈的返回地址做出错误预测。P550 可能对返回堆栈溢出的处理不够优雅,即使测试仅超出返回堆栈容量几个条目,它也会错误预测许多返回。

获取并解码

P550 的前端带有奇偶校验保护的 32 KB 4 路组相联指令缓存,能够提供足够的带宽(12 字节/周期)来为下游 3 宽解码器提供数据。只要代码适合 L1i,前端就可以维持 3 IPC。指令带宽超过该值后会逐渐下降。从 L2 开始,内核仍然可以维持合理的 2 IPC。L3 的指令带宽适用于 1 IPC,尽管您真的希望任何内核上的 L2 代码未命中率都很低。

Arm 选择为 A75 提供更大的 64 KB 指令缓存,使其更有机会满足来自 L1i 的指令端内存访问。在 L1i 未命中时,指令带宽会急剧下降。这在很大程度上取决于实施决策。高通为 Snapdragon 670 提供了 1 MB 系统级缓存。系统级缓存比计算块更靠近内存控制器。因此,它们通常不会针对任何一个块提供高性能进行优化。相比之下,EIC7700X 上的 4 MB L3 与 CPU 集群紧密相关。

获取的指令被解码为微操作,经过重命名器并到达无序后端。

无序执行

SiFive 的 P550 的重新排序能力比 Arm 的 Cortex A75 略高。但是,得益于从 A73 继承下来的无序退出技巧,Arm 可以使其无序执行缓冲区走得更远。在 A75 上,我使用不完整的分支以及不完整的加载来阻止退出。

与 ROB 大小相比,这两个内核都具有足够的寄存器文件容量,尽管其他结构(如内存排序队列)可能有点薄弱。P550 和 A75 的重新排序能力远不及当前的 Intel 和 AMD 内核,甚至不及 Cortex A710 等较新的 Arm 内核。它们更接近 Intel 的 Core 2 或 Goldmont Plus。不过,适度的无序执行窗口远比按序执行要好得多。

两个内核的执行资源分配都考虑到了低功耗和低面积目标。两者之间,P550 具有更灵活的整数端口设置和更多的调度能力来为这些端口提供数据。不过,Cortex A75 也紧随其后,拥有两个 ALU 端口和一个单独的分支端口。标量整数工作负载通常有很多分支,而分支端口不需要到寄存器文件的写回路径。Arm 的设置可能更便宜,同时提供几乎相同的性能。

在浮点方面,两个内核都有两个 FP 端口,能够处理最常见的操作。P550 处理 FP 加法、乘法和融合乘法加法 (FMA),延迟为 4 个周期,这表明内核使用 FMA 单元来处理所有这些操作。毕竟,加法只是一个乘数为 1 的 FMA,而乘法是一个加数等于 0 的 FMA。A75 的 FP 加法和乘法延迟为 3 个周期,而 FMA 执行时间为 5 个周期。Arm 可能会为 FMA 和加法/乘法使用单独的执行单元。或者,Arm 可能有一个 FMA 单元,其路径经过优化,仅用于执行乘法或仅用于加法。Cortex A75 的 FPU 还支持矢量执行,这使其比 P550 更具优势。

微基准测试表明 A75 有 31 个可用于浮点运算的调度程序条目。Anandtech 表示 A75 有两个 8 条目浮点调度程序,但我的测量结果与之不同。P550 总共有 28 个用于浮点运算的调度程序条目。这可能是一个双端口统一调度程序,或两个 14 条目调度程序。我还没有发现只进入一个端口的操作。

内存子系统

P550 是一种小型、低功耗的设计,不需要英特尔、AMD 或 Arm 大核上的高吞吐量内存子系统。内存操作首先由两个地址生成单元 (AGU) 生成地址。一个处理加载,另一个处理存储。两者似乎都由相对较大的调度程序支持,让核心处理加载和存储不平衡的工作负载。Cortex A75 也有两个 AGU,但 A75 的每个 AGU 管道都可以处理加载和存储。两个加载/存储端口非常有意义,因为加载通常远远超过存储,因此 P550 的加载 AGU 可能非常繁忙,而存储 AGU 大部分时间处于空闲状态。

“我们观察到两个加载/存储端口的使用率约为 20%。我们推测,更改为一个专用加载端口和一个专用存储端口不会对性能产生很大影响...事实证明确实如此,这一更改带来的性能损失不到 1%。”David B. Papworth——《调整 Pentium Pro 微架构》

奇怪的是,英特尔在 1996 年设计 Pentium Pro 时就评估了同样的权衡。他们发现使用不太灵活的加载/存储设置只会对性能产生轻微影响。SiFive 可能也得出了同样的结论。不过,P550 确实比 Pentium Pro 具有更多的重新排序能力,因此在缓存未命中时能够更好地为其执行管道(包括 AGU)提供信息。

AGU 生成程序可见的虚拟地址,这些虚拟地址必须转换为物理地址。P550 使用两级 TLB 设置来加速地址转换。第一级 TLB 是完全关联的,这意味着任何条目都可以缓存任何地址的转换。但是,数据和指令端 TLB 都相对较小,只有 32 个条目。更大的 512 条目 L2 TLB 可同时处理指令和数据 L1 TLB 未命中。在数据端,从 L2 TLB 获取转换会增加 9 个周期的延迟。Arm 的 A75 具有更大的 TLB,并且命中 L2 TLB 的 5-6 个周期惩罚较低。

在访问缓存之前,必须根据较旧的存储检查加载地址(反之亦然),以确保正确排序。如果存在依赖关系,则 P550 只有在加载和存储地址完全匹配且两个访问自然对齐的情况下才能进行快速存储转发。任何未对齐的访问(无论是否依赖)都会使 P550 困惑数百个周期。更糟糕的是,未对齐的加载和存储不会并行进行。未对齐的加载需要 1062 个周期,未对齐的存储需要 741 个周期,两者加起来需要超过 1800 个周期。

这种糟糕的未对齐访问行为即使对于低功耗内核来说也是不典型的。Arm 的 Cortex A75 在最坏的情况下,即两个未对齐的依赖访问只需要 15 个周期。

深入挖掘性能计数器可以发现,执行每条未对齐的加载指令会导致执行约 505 条指令。P550 几乎肯定不支持未对齐访问的硬件。相反,它可能会引发故障并让操作系统处理程序在软件中模拟它。

核心私有缓存

P550 拥有适度的无序执行引擎,没有矢量功能,因此不需要从其内存子系统获取大量带宽。然而,延迟非常重要,因为 P550 不具备高性能内核用于容忍内存延迟的大量重新排序能力。与许多 AMD、Intel 和 Arm 设计一样,每个 P550 内核都有自己的 L1 和 L2 缓存,而 L3 是共享的。数据端缓存层次结构的所有级别均受 ECC 保护。

P550 的 32 KB L1 数据缓存是 4 路组相联的,假设没有对齐问题,每个周期可以处理一次加载和一次存储。因此,最大带宽为每周期 16 字节,通过均匀的读写组合实现。延迟为 3 个周期,与许多低时钟核心相匹配。

L2 缓存为 256 KB,8 路组相联。它由两个组构成,延迟为 13 个周期。这种大小和延迟的组合有点过时,因为 Arm 和 AMD 都实现了延迟更低的更大 L2 缓存。然而,P550 的 L2 仍然可以很好地捕捉 L1 未命中并使核心免受 L3 延迟的影响。L2 带宽为每周期 8 字节,处于中等水平,这一限制适用于读取和写入。虽然这不是一个令人印象深刻的数字,但考虑到核心缺乏矢量能力和单负载 AGU,每周期 8 字节应该足够了。

Arm 的 Cortex A75 享有更高的缓存带宽,这要归功于更高的时钟速度和每个级别更多的每周期带宽。

L3 缓存和互连

P550 的互连必须是模块化和可扩展的,才能满足尽可能大的市场需求。消费级路由器或机顶盒可能只需要 2-4 个核心,而小型边缘服务器可能需要更多核心。P550 可以实例化为最多 4 个核心的集群。据推测,集群内的核心共享一个外部接口。多个集群位于“一致系统结构”上,该结构将来自 P550 集群的流量发送到适当的目的地。从 EIC7700X 数据表来看,这个“一致系统结构”很可能是一个交叉开关。

可缓存内存访问指向 L3 缓存,该缓存可在多个 P550 集群之间共享,并可存储以满足多个内核的带宽需求。SiFive 提供 1 MB、2 MB、4 MB 和 8 MB L3 容量选项。最大的 8 MB 选项有八个存储体,为多集群配置保留。我们正在研究的 EIC7700X 具有 4 MB L3 和四个存储体。因此,存储体数量与内核数量相匹配。

微基准测试表明 L3 可以为每个核心提供每周期 8 字节的带宽。总体而言,EIC7700X 的四核 P550 集群拥有约 43.88 GB/s 的 L3 带宽。L3 延迟约为 38 个周期,相当不错,考虑到缓存的灵活性,这个数字还不错。相比之下,Arm 的 Cortex A73 使用更简单的两级缓存设置。A73 的 L2 兼作 L1D 未命中的第一站和大型最后一级缓存。这意味着妥协,因此 1 MB L2 的容量小于 EIC7700X 的 L3,但在 25 个周期时具有更好的延迟。

L3 未命中则指向内存端口。根据实施目标,P550 多集群复合体可以有一个或两个内存端口,每个端口的宽度可以是 128 位或 256 位。每个内存端口可以跟踪最多 128 个待处理请求,以实现内存级并行性。对 IO 或不可缓存地址的不常见请求将被路由到两个 64 位系统端口之一或一个 64 位外围端口。实施者还可以使用一个或两个前端端口,这让其他代理可以通过多集群复合体进行一致的内存访问。

Eswin 选择使用单个内存端口(可能为 128 位宽)和两个系统端口。第一个系统端口的地址空间包括 256 MB PCIe BAR 空间、PCIe 配置空间和 4 MB ROM。第二个系统端口可访问 DSP 的 SRAM 等。

这些端口连接到使用 AXI 协议的片上网络。此时,一切都取决于实施者,而不受 SiFive 控制。对于 EIC7700X,Eswin 使用了两个 DDR 控制器,每个控制器都有两个 16 位子通道。在 SiFive Premier P550 开发板上,它们连接到 16 GB 的 LPDDR5-6400。内存控制器以 SDRAM 时钟的 1/4 运行,即 800 MHz。DRAM 加载到使用延迟并不好,为 194 纳秒,比 L3 延迟大约高出 165 纳秒。无法判断这种延迟中有多少来自穿越片上网络,有多少来自内存控制器。但无论如何,EIC7700X 上的内存延迟都比其他 LPDDR5 设置(如英特尔的 Meteor Lake 或 AMD 的 Van Gogh(Steam Deck SoC))差得多。

我测量了 16.74 GB/s 的 DRAM 带宽,这远远低于 LPDDR5-6400 即使在 64 位总线下也能达到的带宽。EIC7700X 使用了一些总线宽度来进行内联 ECC,但即使考虑到这一点,实际带宽也远远低于理论值。不过,这种带宽对于没有矢量功能的低时钟四核设置来说应该足够了。

核心到核心延迟

极少数情况下,互连可能需要执行跨核心传输以保持缓存一致性。Eswin 的 EIC7700X 数据表称,内存子系统有一个“基于目录的一致性管理器”,这意味着内存访问会检查目录,以确定是否需要发送探测或可以正常沿着内存层次结构进行。与广播策略相比,使用目录可以在核心数量增加时控制探测流量。

Anandtech 和其他网站使用“核心到核心”延迟测试来检查一个核心观察另一个核心的写入需要多长时间,我也编写了自己的测试版本。虽然确切的方法不同,但结果应该与 Anandtech 的结果大致相当。EIC7700X 上的核心到核心延迟相当高。

即使在 A75 和 A55 核心之间进行传输,高通的骁龙 670 的表现也更好。

虽然较高的核心到核心延迟不太可能影响应用程序性能,但确实让人感觉 SiFive 的 P550 不那么精致。

最后的话

RISC-V 是一个年轻的指令集,而 SiFive 是 CPU 设计行业的新玩家。高性能 CPU 设计极具挑战性,从该领域的参与者数量之少可见一斑。根据该公司的数据表,P550 的目标是“在严格限制的功率和面积占用内实现最高性能”。它不会与 AMD 的 Zen 5、英特尔的 Lion Cove 或高通的 Oryon 等产品正面对抗。P550 的乱序引擎在尺寸上更接近英特尔 15 年前的 Core 2。再加上比 Core 2 运行的时钟速度低得多的时钟速度,P550 实际上是一个低功耗、性能适中的内核。它最适合轻量级管理任务,在这类任务中,有序内核可能会有点迟缓。

更重要的是,P550 是 SiFive 推动 RISC-V 实现更高性能目标的垫脚石。不久前,SiFive 主要关注微型有序内核,这些内核不适用于微控制器以外的领域。借助 P550,SiFive 构建了一个由功能强大的缓存层次结构支持的合理平衡的无序引擎。他们掌握了基础知识,这一点非常重要,这一点再怎么强调也不为过。事实证明,无序执行对于构建高性能通用 CPU 至关重要,但也很难实现。事实上,英特尔和 IBM 都试图放弃无序执行,因为它增加了太多复杂性,结果却发现 Itanium 和 POWER6 的策略并不好。考虑到这一点,SiFive 的进展令人鼓舞。

不过,P550 只是 SiFive 打造更高性能 RISC-V 内核的第一步。作为这一旅程的一步,P550 感觉更像 Arm 早期的无序设计之一,例如 Cortex A57。到 A75 问世时,Arm 已经在设计无序 CPU 方面积累了丰富的经验。因此,除了低功耗和热预算所需的明显牺牲外,A75 是一个经过精心打磨且功能全面的内核。相比之下,P550 的边缘比较粗糙。它的时钟速度很低。未对齐访问惩罚非常荒谬。缺乏向量支持。许多程序不会遇到 P550 最严重的缺陷,但 SiFive 还有很长的路要走。

在这方面,我还看到了 P550 与英特尔首款乱序 CPU 之间的相似之处。20 世纪 90 年代中期的 Pentium Pro 在运行 16 位代码时表现不佳。但尽管在某些重要领域缺乏完善,但整个内核设计精良,让英特尔有信心应对更复杂的 CPU 设计。SiFive 此后宣布了更复杂的乱序设计,如 P870。我很高兴看到这些内核在即将推出的芯片中实现,因为它们看起来非常有前途。

来源:智慧芯片

相关推荐