在哪些问题上 SIMD 的性能优于 Cray 式向量?

rwa*_*ace 4 simd instruction-set vectorization cpu-architecture

旨在提供高性能数字运算的 CPU 最终会采用某种向量指令集。基本上有两种:

  1. SIMD。这在概念上很简单,例如,您不仅拥有一组 64 位寄存器及其上的操作,还拥有第二组 128 位寄存器,并且可以同时对两个 64 位值的短向量进行操作。它在实现中变得复杂,因为您还希望可以选择对四个 32 位值进行操作,然后新一代 CPU 提供 256 位向量,这需要一套全新的指令等。

  2. 较旧的 Cray 风格向量指令,其中向量一开始很大,例如 4096 位,但同时操作的元素数量是透明的,并且要在给定操作中使用的元素数量是指令参数。这个想法是,你预先减少一点复杂性,以避免以后出现复杂性。

有人认为选项 2 更好,并且这些论点似乎有道理,例如https://www.sigarch.org/simd-instructions-considered-harmful/

至少乍一看,选项 2 似乎可以完成选项 1 可以做的所有事情,而且更容易,而且总体上更好。

是否存在相反情况的工作负载?SIMD 指令在哪里可以完成 Cray 式向量无法完成的任务,或者可以更快或使用更少的代码完成任务?

Joh*_*pin 5

“传统”矢量方法(Cray、CDC/ETA、NEC 等)出现在晶体管预算有限且商用低延迟 SRAM 主存储器有限的时代(~1976 年至~1992 年)。在这种技术体系中,处理器没有晶体管预算来实现无序操作的完整记分板和互锁,而无序操作目前可用于允许多周期浮点操作的流水线操作。相反,创建了向量指令集。向量算术指令保证向量内的连续操作是独立的并且可以流水线化。扩展硬件以允许并行进行多个向量操作相对容易,因为依赖性检查只需要“每个向量”而不是“每个元素”完成。

Cray ISA 与 RISC 类似,数据从内存加载到向量寄存器中,逐个寄存器执行算术,然后将结果从向量寄存器存储回内存。最大向量长度最初为 64 个元素,后来为 128 个元素。

CDC/ETA 系统使用“内存到内存”架构,使用算术指令指定所有输入和输出的内存位置,以及 1 到 65535 个元素的向量长度。

“传统”向量机都不使用数据缓存进行向量操作,因此性能受到从内存加载数据的速率的限制。SRAM 主存储器占系统成本的主要部分。1990 年初,SRAM 的每位成本仅为 DRAM 的 2 倍左右,但 DRAM 的价格下降得如此之快,以至于到 2002 年,SRAM 的每 MiB 价格已是 DRAM 的 75 倍——这已经远远不能接受。

传统机器的 SRAM 存储器是可字寻址的(64 位字),并且存储量很大,可以实现几乎全速的线性、跨步(只要避免 2 的幂)和随机访问。这导致了一种广泛使用非单位步长内存访问模式的编程风格。这些访问模式会导致缓存计算机上的性能问题,并且随着时间的推移,使用缓存系统的开发人员会放弃使用它们,因此代码不太能够利用矢量系统的这种功能。随着代码被重写以使用缓存系统,人们慢慢发现缓存对于向量机上运行的大多数应用程序来说工作得很好。缓存数据的重用减少了所需的内存带宽量,因此应用程序在基于微处理器的系统上的运行比主内存带宽比预期的要好得多。

到 1990 年代末,传统向量机的市场几乎消失,工作负载主要转移到使用 RISC 处理器和多级缓存层次结构的共享内存机器。开发了一些政府补贴的矢量系统(尤其是在日本),但这些对高性能计算影响不大,对一般计算也没有影响。

故事还没有结束——经过多次不太成功的尝试(由几个供应商)让向量和缓存很好地协同工作后,NEC 开发了一个非常有趣的系统(NEC SX-Aurora Tsubasa),它结合了多核向量寄存器处理器设计采用DRAM(HBM)主存,以及有效的共享缓存。我特别喜欢使用单个执行线程生成超过 300 GB/s 的内存带宽的能力 - 这是 AMD 或 Intel 处理器的单个线程可用带宽的 10 到 25 倍。

因此,答案是,即使在 SIMD 被纳入之前,带有缓存存储器的微处理器的低成本也将向量机赶出了市场。SIMD 对于某些专门的操作具有明显的优势,并且随着时间的推移变得更加通用——尽管随着 SIMD 宽度的增加,其优势逐渐减弱。从架构意义上来说,矢量方法并没有消亡(例如,NEC 矢量引擎),但它的优点通常被认为被软件与主流架构模型不兼容的缺点所压倒。