中文 英语

用矢量指令加速AI

使用矢量引擎的用途、挑战和权衡。

受欢迎程度

整个行业正在寻找加速机器学习应用程序的最佳方法,而优化矢量指令的硬件正在成为这一努力的关键要素。

向量指令是一类能够并行处理数据集的指令。在一个操作中处理整个整数或浮点数数组,消除了处理数组中常见的循环控制机制。这反过来又提高了性能和电源效率。

公司首席执行官Shubhodeep Roy Choudhury表示,这一概念尤其适用于用于这些数据集的稀疏矩阵运算,通过向量化,可以实现显著的性能提升Valtrix系统

然而,这比看起来要难得多。涉及到将数据移进和移出内存和处理器的设计问题,由于数据集的复杂性和总体大小的增加,还存在验证挑战。然而,随着数据量的增加,对这些性能/功率改进的需求也在激增,而向量指令是这一难题的重要组成部分。

“虽然英伟达在让这些应用程序在他们的gpu上运行方面做得很好,但这些应用程序非常昂贵,非常耗电,而且并不是真正针对它的,”Nvidia的首席执行官Simon Davidmann说治之.“现在,工程团队正在构建专用硬件,这些硬件将快速运行这些人工智能框架。开发人员正在寻找能够快速运行机器学习算法的向量。”

向量指令或扩展并不新鲜。事实上,它们是现代CPU体系结构的关键部分,用于从图像处理到科学模拟的工作负载。英特尔、Arm、ARC、MIPS、Tensilica等公司已经为微软等后来者铺平了道路RISC-VISA。真正发生变化的是两者的专业化和优化程度不断提高。

Arm在Armv6中首次获得了对固定宽度SIMD样式向量的支持,并迅速发展为Armv7-A中的Neon,根据Armv6产品管理总监Martin Weidmann的说法手臂的建筑与技术集团。最近,Arm引入了可伸缩向量扩展(Scalable Vector Extensions, SVE),支持可变向量长度和谓词。SVE已经被采纳,包括在世界范围内最快的超级计算机

CPU架构,例如Arm架构,本质上是硬件和软件之间的契约。Weidmann解释说:“架构描述了硬件必须提供的行为,以及软件可以依赖的行为。”“这其中至关重要的是一致的行为。开发者需要相信任何实现这种架构的设备都能提供相同的行为。”

例如,开发人员必须确保在基于Arm的设计上运行的任何代码都能看到Arm架构参考手册中描述的行为。在这一点上,Arm创建了遵从性测试资源。

Weidmann指出,为像现代CPU这样多功能的东西编写全面的合规套件始终是一个挑战。向量扩展只会增加这一挑战,特别是在以下领域:

  • 矢量长度不可知(VLA)在SVE和SVE2中的测试
  • 处理多个元素并发处理所引入的依赖关系,包括异常处理和浮点正确性
  • 分散-聚集负载和存储操作的复杂性。


图1:如何并行处理较长的向量的示例。来源:手臂

ARC处理器的产品营销经理Graham Wilson说Synopsys对此他指出,工程团队正在采用处理能力的组合,将传统上运行在控制器核心上的代码与运行在控制器核心上的代码配对DSP.所有这些现在都合并在一个统一的处理器上进行计算。

“我们看到越来越多的传统矢量dsp更多地扮演标量的角色,或者拥有更多控制代码的能力,因为这在很大程度上是由运行在物联网边缘的设备驱动的,它们需要更小、更低功耗的计算。还有更广泛的代码范围——从控制代码、DSP代码到矢量代码——现在还有人工智能算法计算,由单个处理器上运行的小尺寸和低功耗需求驱动。我们看到了一个趋势,从更传统的矢量dsp,有更好的控制计算和操作,以及从正常的控制器进程,如Arm核心和其他,计算更多的矢量代码。矢量扩展是基本控制器进程的路径,允许它操作和运行矢量操作,以及单个控制器核心上的矢量代码。”

SoC设计人员可以免费获得这些好处,因为它包含在CPU内部。“它通常不会直接接触它的外部,所以从硬件设计师的角度来看,如果他们包括一个碰巧有向量扩展的CPU,它对他们来说本质上是一样的,”HLS平台项目总监Russell Klein说Mentor是西门子旗下的企业

克莱因说,软件设计者将需要利用这一点,并不得不担心如何对这些矢量扩展进行编程。“这一直是一个挑战。在传统的C编程语言中——以及人们使用c++来编写在这些cpu上运行的程序——并没有从特定的C结构直接映射到向量扩展的使用。通常,有许多不同的方式可以访问这些特性。而不是写和C代码,最基本的是用汇编语言写,然后可以直接调用矢量指令。大多数人不喜欢这样做,因为工作量很大,而且不能很好地与他们在其他地方使用的C代码融合。”

为了解决这个问题,处理器公司如Arm和Intel已经编写了库来利用这些矢量指令,并提供了一个库来进行快速傅里叶变换或矩阵乘法运算。他解释说:“他们已经走在了前面,用汇编语言编写了所有的代码,以CPU设计者所期望的方式利用这些矢量处理操作。”“然后用户编写程序只需要调用专门的FFT或矩阵乘法,它就会使用它。对于英特尔和Arm来说,这是一种很容易传播的方式,我希望RISC-V社区也能做同样的事情。圣杯是让你的C编译器足够聪明,能够查看你的循环,并理解这可以向量化。”

这是一个过去没有解决的难题,尽管团队建设正在进行工作LLVM克莱因说,他们声称他们能够识别可向量化的循环并调用向量指令。

集成问题
另一个重要的考虑是矢量单元应该如何集成到一个核心中,无论它是紧密耦合的还是一个独立的单元。

“如果你看看已经在研究这个问题的团队,几乎所有人都决定采用与主管道连接的独立矢量单元,就像在执行阶段一样,”Zdenek Prikryl说Codasip.“然后,基本上,你可以分别在向量单位中进行操作。除非存在依赖关系,否则不必暂停主线程。这是我们的目标——有一个独立的引擎,与主核心通信或紧密耦合,但不在主核心的管道内。在开始的时候,应该有一些类似于乘法-累加的指令提示,或者可能是用于加载和存储的流和整数提示,等等。最后,我们有一些共同的阶段,你可以把数据绑定到注册文件。还要记住内存子系统,因为如果你有一个矢量引擎,就有大量的数据需要处理。因此,内存子系统也是一个关键点,甚至可能是一个更大的问题,因为你必须能够为引擎提供动力,同时获取数据。”

对于向量引擎来说,高吞吐量是必不可少的,因此512位这样的宽接口和可以快速提供数据的紧密耦合存储器(tcm)是最佳选择。Prikryl说:“这些是我们在设计之初必须问的主要问题。”“这需要创建一种不被内存子系统阻塞的架构,也不被主要标量部分的管道阻塞,因此向量可以产生输出,可以与内存一起工作,只在需要通信时才请求主核心。”

RISC-V矢量引擎允许选择寄存器宽度。Prikryl说:“如果你的目标是一个更小的系统,它就可以更小。“如果你的目标是大型服务器,那么你就有非常宽的寄存器,你必须以某种方式将内存带宽与这些寄存器联系起来。然后你会受到这个限制,那么你的目标吞吐量有多大呢?通常你必须遵循现有的标准,比如Amba标准。还有一些限制,比如最多1024位。但与此同时,如果你的目标是如此广泛的接口,你通常会受到延迟或频率的影响,因为它非常广泛。所以这是一种妥协。我们愿意提供来自中医的快速数据,以便能够合理地快速地匹配数据。同时,在内存子系统的情况下,我们必须考虑编程模型。 I’d also like the possibility to load the data through the standard cache because the programming model is easier. If you write the C code, then eventually you can store the vectors, not only to the vector in memory, but also to the memory of the cache. And then, with the scalar part you can touch the vector and change things here and there.”

但另一个需要考虑的问题是,必须有办法给引擎提供动力。引擎应该能够与标准缓存内存子系统的标量部分通信,并且必须以这种方式进行设计。“我们必须平衡编程模型,让用户能够在机器上编程,”他说。“这应该尽可能简单,这意味着我们应该告诉他们如何进行向量化。我们应该给它们堆栈操作,诸如此类的东西。这些通常是通过主存和TCM的组合来完成的。这不仅仅是一个必须以某种方式预加载数据的TCM。这两个世界可以结合在一起,所以编程很容易,然后我可以通过TCM提供数据,仍然可以在那里提供数据。但如果我需要一些不是引擎关键部分的东西,它可以在缓存上工作。不需要去看中医。 In this way, the memory subsystem can be tricky.”

Mentor的Klein指出,一个值得关注的领域是与寄存器绑定的内存子系统。他说:“你需要能够将数据输入这些寄存器来执行操作,然后你需要将结果取出来。”“例如,在Arm核心上,你可以有一个高达2048位宽的寄存器。如果总线到内存的宽度是128位,那么向量处理单元很快就会缺少数据因为你不能足够快地从主存中取出数据。然后还需要查看从缓存到CPU的路径。这可能比通往主存的路径更宽,因为从根本上讲,构建一个矢量处理单元并不难,它会消耗比主存内外可用带宽更多的带宽。如果是这种情况,那么引擎就过度设计了,你无法足够快地获得足够多的数据,也无法足够快地吸取结果,从而无法真正利用现有的加速。”

此外,当从具有统一内存子系统的控制器转换到具有矢量操作的控制器时,需要对数据进行对齐和打包。这种矢量工作收集所有这些数据,然后在单个SIMD(单指令,多数据)操作上运行它。因此,内存中的空间需要预打包和预分配。

Synopsys公司的威尔逊说:“你还需要能够把数据带进来。“有时这些数据,如果你去一个很长的向量长度,也是相当长的,它通常比你可能拥有的通用系统内存长得多。因此,您将需要扩展,或者一些传统的dsp可能使用专用的内存负载存储架构来连接到这个矢量数据内存。这使得你可以有效地将数据输入,计算,然后发送出去。”

验证向量
向量指令扩展和向量引擎的验证通常与标量指令没有太大区别。

的验证经理Darko Tomusilovic说:“你需要像验证其他处理器一样验证这些处理器Vtool.“你需要了解每条指令的作用,如何在你的环境中建模,如何预加载一组随机指令来刺激它,或者编写适当的软件,这些软件将被编译成你运行的代码。除此之外,这是一个经典的过程,就像任何其他的处理器验证一样。当然,对这些指令建模更加复杂,但就工作流程而言,两者是完全相同的。”

罗伊·乔杜里对此表示同意。验证向量指令的方法与标量指令没有太大的不同。这个过程必须从一个全面的测试套件开始,它可以扫描所有指令的配置设置,并将测试结果与黄金参考进行比较。一旦清理了配置,重点就应该转移到有约束的随机和互操作性测试上。还需要涵盖向量化的用例,以确保工作负载和应用程序平稳运行。”

罗伊·乔杜里说,与此同时,当涉及到向量时,还有一些验证方面的考虑。“由于矢量指令操作大量数据,因此任何测试所观察的整体处理器状态都非常大。一些向量实现,如RISC-V,被设计得非常灵活,允许用户配置元素大小、起始元素、向量寄存器组的大小等。因此,每条指令必须检查的配置数量是巨大的。这些因素加起来增加了核查的复杂性。”

换句话说,验证需要向左移动。Imperas的Davidmann表示:“持续集成和测试的软件技术正在被硬件SoC和处理器设计团队所采用。“经常被引用的估计是,设计项目60%到80%的成本和时间用于验证,这是一种过度简化。设计就是验证。当设计团队开发功能规范时,测试计划是所有讨论的中心。验证不再仅仅是设计阶段结束时的一个里程碑。通过RISC-V的开放标准ISA,该规范除了自定义扩展之外,还允许许多选项和配置。当设计人员选择和定义所需的特性时,需要在每个状态下共同开发详细的测试计划。协同设计实际上是硬件、软件和验证作为一个持续同时进行的过程。”

结论
除了所有的设计和验证挑战之外,设计矢量指令的关键之一是理解目标的最终应用程序。

克莱因说:“最终,你要放入一个矢量引擎,因为你要进行某种信号处理或某种图像处理,或者更常见的是推理。”“我们之所以听到这么多,是因为机器学习算法的普及。在那里,对大型数组进行乘法-累加操作。它真的很重复,有很多数据,它很适合这个向量数学。假设你正在使用一种推理算法来查看卷积核的特征映射的预期大小,以及它们如何适合你正在考虑构建的向量单元。如果你有9个8比特的卷积核,把一个1024比特的向量处理单元放进去是没有用的,因为你只有72比特的核数据。通过这种方式,了解最终应用程序,并考虑到您需要支持的数据模式和计算模式,是获得加速器和I/O带宽的正确组合的方式,以及能够有效满足您正在寻找的应用程序的总体设计。”

相关的
RISC-V正在获得吸引力
第1部分:可扩展指令集体系结构正在引起整个行业和供应链的关注。
RISC-V:会有其他开源内核吗?
第三部分:开源工具的现状,以及2025年RISC-V的前景。
RISC-V市场,安全和增长前景
专家:为什么RISC-V受到如此多的关注,还需要做什么,以及它可能在哪里取得最大的成功。
RISC-V的挑战和机遇
谁能从开源ISA中赚钱,RISC-V生态系统的当前状态,以及供应商之间的区别。
RISC-V的扩展足迹
与开源ISA合作的市场机遇和技术挑战
开源硬件发展势头
RISC-V推动了对这个市场的新关注,但开源硬件的成本/收益等式与软件不同。
开源的验证
理清开源验证的含义并不容易,但它为新方法敞开了大门。



留下回复


(注:此名称将公开显示)

Baidu