Loading

CiMLoop论文解读

CiMLoop:一个灵活、准确、快速的存内计算建模工具

最近在推进CiM仿真器方面的工作,其中MIT发表的CiMLoop工作之前就在关注,但一直没有沉下心好好研读过,现在抽出一些时间来好好的阅读和分析一下。

摘要

存内计算是一个加速神经网络的潜力方案,因为其可以避免高能耗的权重数据搬运,并且使用存储阵列提供低能耗,高密度的计算。这些优势引发了对CiM的整个技术栈的研究,但CiM研究往往只关注于技术栈中的一层(例如器件、电路、架构、负载或者映射),或者只研究一个设计点(例如制造一个芯片)。我们需要一个全栈的建模工具来评估设计决策对整个系统的影响(例如观察一个电路对整体系统能耗的影响)并且进行快速的早期CiM软硬件协同设计空间的探索。

为了解决这一需求,CiMLoop的作者们提出了一个开源的建模工具来建模不同的CiM系统,并探索整个CiM技术栈中的设计决策。CiMLoop引入了(1)一个灵活的指定方式,使得用户可以自己描述,建模并将负载映射到电路和架构上(2)一个精确的功耗模型用来捕捉网络操作数,硬件数据表示以及电路传播的模拟/数字值之间的交互关系(3)一个快速的,其速度比其他高精度模型快数量级的统计模型用于探索设计空间。

使用CiMLoop,研究者可以评估不同层级的CiM技术栈的设计选择,并在所有层次进行协同设计,公平的比较不同的实现,并快速探索设计空间。

从摘要可以看出这个工作的insight非常好,目前CiM领域确实急缺这样一个全栈的分析工具,另外也强调了这一工具的三个重要的评估指标:灵活、准确和快速,这一理念值得follow。

介绍

存内计算是一个解决深度神经网络中高数据搬运能耗和大量计算的潜力方案,CiM系统直接在存储器内进行计算,使得它们可以(1)将网络权重保持于存储器内避免高能耗的数据搬运(2)使用大型存储器阵列来高密度、低能耗的计算大量的并行成累加操作。

最近许多存内计算的工作探索了CiM技术栈的不同层次,包括CiM阵列内的器件级;执行计算、数模转换、数据搬运和其他操作的电路级;将设备、电路以及其他组件组织在一起的架构级;待加速的神经网络的负载级;和在硬件上进行空间和时间调度的映射级

一般来说,研究者们值研究这些层级中的一个,但是CiM技术栈的层级之间是相互关联的,因此一个全栈模型是有必要的,从而能够完整的审视所有的模型。全栈建模非常的重要,因为评估一个层次的选择,需要结合其他的层次。例如,在选择电路时,我们希望知道它们会如何影响整个系统在运行一个给定负载时的能耗/吞吐率。出于这一原因,我们必须进行全栈的协同优化才能找出最能够符合需求的设计

为了实现全栈建模,我们需要一个能够表示整个CiM层级的建模工具,并且能够分析它们如何相互影响。为了实现这一目的,这个工具必须要能够灵活地建模设计决策的空间,准确地比较这些选择,并且快速的探索设计空间。下表比较了CiMLoop和之前的建模工具在解决这些关键挑战上的情况:

image

CiM建模的挑战:

  1. 灵活性挑战:建模工具必须能够建模CiM设计空间,但不同的CiM实现引入了不同的电路和架构,为了建模设计空间,工具必须要让用户能够简单的定义电路,架构以及数据的流动。

    这件事富有挑战之处在于,数据移动在不同的架构中可能是不一样的(例如,SRAM缓存在存储层级中和其他存储的数据交互与存储)。为了解决这一挑战,建模工具必须要灵活,意味着它能够让用户简单的描述大范围的组件,它们如何互联以及他们之间如何移动数据。不幸的是,之前的CiM建模工具都是不灵活的,或者缺少电路级的建模。

    解决这一问题带来的第二个挑战是:灵活的建模工具必须要描述许多不同类型的组件,包括架构层级(例如DRAM+L3/L2/L1 Cache)以及一系列电路(例如数据转换器,SRAM单元,寻址电路)。为了解决这一问题,建模工具还需要让用户可以简单的描述有着不同组件的复杂设计。

  2. 准确性挑战:建模工具必须能够精确的建模能耗,从而正确的影响设计决策,但器件和电路能耗存在数据值关联性,意味着受到每个组件传输的数据值的影响(例如,一些ReRAM器件的功耗与计算的MAC值成正相关),数据值关联性可以显著影响整体系统能耗,所以我们需要一个有着高能耗准确性的建模工具,在这个工具中我们可以捕捉数据值关联性。不幸的是,之前的模型使用不准确的固定能耗或固定功耗模型,并没有建模数据值关联性

  3. 建模速度挑战:建模工具必须要足够快速以探索巨大的设计空间,但是精确的数据值关联性建模工具依赖于数据值,仿真大量数据值在CiM系统中的传播非常的缓慢,不幸的是之前的工作没有解决这一问题,精确的模型非常慢,而快速的模型不够精确。

CiMLoop为了解决上述问题,提出了一个全栈CiM建模工具,有着灵活的用户定义系统,快速精确的统计能耗建模。CiMLoop作出了以下的关键贡献:

  • 一个灵活的指定方式来描述用户定义电路与架构的CiM系统,该指定方式包含了(1)电路与架构数据流动模式的方向表征(2)将电路与架构在统一层次进行描述的表征。该层次使得用户可以简单的定义和映射工作到一个有着许多不同类型的电路、架构和数据移动模式的系统上。
  • 一个精确的组件能量数据值关联性模型用于捕捉深度神经网络操作数,数据表示,以及组件传播的数据值的交互。使用这一接口,用户可以开发一套可以简易的用于用户定义系统中的CiM组件模型
  • 一个快速的统计模型用来计算考虑了数据值关联性的能耗。这一模型可以一次性计算每个组件每次操作的平均能耗,使得CiMLoop可以(1)使用固定的运行时间来建模任意数量的组件/行为(2)在多种映射上同时进行功耗计算。作为结果,CiMLoop相对于之前的精确建模工作取得了数量级的速度提升。
  • 使用四个最近发布的CiM设计进行了样例研究。在这些样例中,作者们验证了CiMLoop的准确度并且展示了CiMLoop可以(1)建模不同的CiM实现(2)探索不同的CiM技术栈层次之间的权衡(3)建模完整系统(4)公平的比较不同的CiM设计

通过解决这些挑战,CiMLoop使得研究者们可以跨越层级的评估和协同设计,公平的比较CiM实现并且快速的探索CiM设计空间。

这段介绍最主要的是分析了目前存在的仿真器的挑战,将CiM的完整技术栈抽象为器件级、电路级、架构级、负载级、映射级共五个层级,并完整的阐述了CiMLoop为了达到灵活、准确、快速三个目标所采取的具体方式,首先在灵活性方面,CiMLoop提供了灵活的指定方式,使得用户可以直接指定数据流方向,并且可以描述不同的电路、架构以及数据移动模式;其次在准确性方面,CiMLoop的精确度来源是它考虑了能耗的数据关联性,相比之前的固定能耗模型提升了进度;最后是速度方面,CiMLoop采用了快速统计模型来计算能耗,从而避免了仿真大量数据值带来的仿真速度问题。并且再次强调了CiMLoop的主要目的:使得研究者们可以跨越层级的评估和协同设计,公平的比较CiM实现并且快速的探索CiM设计空间。

背景与动机

首先介绍存内计算在加速深度神经网络上的背景以及为什么全栈建模对于探索CiM空间是重要的,基于此,再进一步讨论CiMLoop解决的三个挑战。

深度神经网络层中的张量操作使用巨大的输出,权重与输出张量,将它们从存储中搬运是非常耗能的。此外,张量操作需要大量的MAC操作,这一计算也是耗能耗时的。

数据搬运占据了深度神经网络能耗中很大部分的比重,而CiM可以通过直接在存储阵列内进行计算来减少能耗开销,作者们将其定义为互联存储单元的二维格点(例如SRAM位单元或者RRAM器件)。大多数情况,CiM系统需要将深度神经网络权重保存在存储器内,因为它们在深度神经网络的推理过程中它们保持不变。许多CiM在实现时进一步通过模拟域运算来减少能耗和延迟,其中模拟MAC操作可以通过一个或几个存储单元实现,而非完整数字乘加电路。

一般来说,一个CiM的实现通过宏单元的形式来发表,作者们将其定义位一个存储器单元阵列加上计算完整MAC所需的额外组件。这与系统不同,我们一般将系统定义为一个或多个宏单元加上一个存储层级以及存储层级之间的互联。

一个常见的CiM的拓扑如下图所示,在该拓扑中,一个DAC将模拟输入提供给存储阵列的行。每个阵列中的存储单元计算一个输入与其存储权重的模拟MAC操作。一列内的每个存储单元的模拟输出相加在一起,并通过一个ADC读出以获得数字输出。

image

研究者们探索了许多其他的CiM拓扑,电路,以及模拟或数字计算的方式。CiMLoop建模了CiM单元空间,并将CiM与系统建模工具集成在一起。

CiM的研究跨越了如下的层级:

  • 器件:这些组件构成了每个存储单元。公开的CiM一般使用SRAM,DRAM,ReRAM或者STT-RAM
  • 电路:这些组件执行计算,模数转换,存储,数据移动以及其他操作
  • 架构:将组件组织成一个更大的系统(例如,每个组件的数量以及组件之间如何连接)
  • 负载:需要运行的深度神经网络,我们将其建模为一系列具有不同形状和值的张量的扩展 Einsum 运算
  • 映射:负载在系统上的时间与空间调度

全栈建模意味着将所有的层级同时建模,其重要性出于两个原因。首先,在评估一个给定层级的选择时,所有的层级都需要纳入考虑。一种不考虑全栈的失败建模如下图所示,在探索不同的运行ResNet18的CiM的阵列尺寸时,最低功耗的CiM有着最小的阵列,因此使得其即使是小的张量也能有高利用率和低能耗。而最低系统能耗的CiM使用了更大的阵列。尽管大阵列经常无法完全被利用,但是其能存储更多的权重,使得其可以减少向其他存储层次的数据搬运,从而降低系统能耗。

如果仅仅优化CiM的能耗,我们会错误的得到一个高能耗的系统。只有考虑全系统,我们才能做出在一个层级上的最优选择。

image

第二个需要全栈建模的原因是,协同多层次可以找到最优的系统。如下图所示,从上图中的最低能耗的CiM开始,测量调整DAC分辨率(电路)以及CiM阵列尺寸(架构)的影响。优化电路时,使用更高分辨率的DAC可以同时处理更多的输入位,从而降低阵列需要被激活的次数,并减少每次MAC的能耗。优化架构,除了使用高分辨率的DAC之外,使用更大的阵列进一步减少了在给定的MAC次数下阵列的激活次数。对于更小的张量,阵列无法充分得到利用,且高分辨率的高能耗DAC导致更大的能效损失。最终,在协同优化CiM使用更大的阵列以及更低分辨率的DAC后,大阵列可以在每次激活时计算许多的MAC,而低分辨率的DAC可以在大阵列未被充分利用的情况下保持低能耗。因此协同优化使得我们能够找到一个产生低能耗系统的设计决策。

image

一个CiM由一系列的组件构成(例如器件,电路和架构)以及它们用于搬运数据的互联。组件和数据移动选择决定了系统的面积/能耗,以及系统能够进行的计算,所以有必要在建模CiM时表征这些选择。

不同的CiM可以使用不同的组件以及数据移动模式来优化不同的设计目标。一个选择组件和数据移动方式的关键点是它们如何利用数据重用来减少能耗。重用可以通过减少组件进行搬运或者计算的次数来节省能耗。例如,权重可以被存储在存储单元里,并在时间上重用(跨越周期)来减少权重从分离的存储器中取数的次数。另一个例子是在最开始的CiM拓扑的例子中,通过在不同的阵列的列中重用模拟输入,可以减少DAC将输入转换为模拟的次数。

在涉及到不同的组件,数据移动方式以及重用时有许多有趣的设计选择。下图展示了公开发表的CiM中的一些介绍ADC功耗的方法:

image

在基础CiM中,多个阵列行复用输出(例如,N行阵列可能会求和N次MAC结果,并将结果从一次模数转换中读出)。为了进一步减少ADC功耗,不同的CiM使用了不同的粗略:

  • CiMA通过将不同列在线上求和实现模拟输出的复用
  • CiMB通过模拟加法器将不同列求和来复用模拟输出
  • CiMC通过模拟累加器多个周期累加来复用模拟输出
  • CiMD使用模拟MAC电路间歇性服用输出产生使用不同权重位的单一输出
  • 数字CiM复用数字的输出以避免使用ADC

每个策略都有自己的权衡。额外的组件消耗面积与能耗。组件也会引入映射与数据移动的限制(例如对于CiMB,相邻列必须要存储相同位数的权重,对于CiMA,相邻列必须存储来自不同权重的位)

在广阔的CiM设计空间内,这些知识集中可能的组件,而减少ADC能耗也只是一个需要解决的问题。

关键建模1:上述问题带来的挑战是,建模工具必须要灵活,意味着可以将负载描述和映射到不同的组件集合以及不同的数据移动/重用模式上。此外,也需要考虑与全系统关联性,包括缓存层次和互联。全系统建模必须要有一种可以简单的描述有着不同类型组件的复杂设计的表示能力。

为了建模设计空间,有必要让用户来定义系统中的组件以及它们的互联方式。NeuroSim和NMSim仅仅建模了基础CiM,并且不让用户增加组件或者定义数据移动方式。Timeloop+Accelergy让用户可以定义架构级的组件,但是无法建模电路数据搬运或重用(例如一个SRAM缓存中的存储单元和传感放大器)。出于这一原因,这些工作均无法描述CiMA,B,C,D。

此外,器件/电路能耗是数据值关联的,即会受到系统中组件传播的数据值的影响。我们可以将数据值关联性分解为下述三个部分:

  1. 神经网络负载:系统处理的深度神经网络,可能会在神经网络层/张量的分布,符号以及稀疏度上存在差异。

  2. 表征:数据值如何表示,取决于硬件如何表征算子。首先,算子被编码,意味着表示为比特。接着它们被切片,意味着比特被分配到不同的器件和电路上。表征会随着系统中的不同张量和不同的组件而改变。

  3. 电路:不同的电路消耗不同的能量来传播不同的数据值。例如,一些ADC或者DAC在转换小的值时能耗更小。

下图展示了这三个部分对DAC的影响。数据值依赖性会对于所示类型的DAC的能耗有2.5倍的影响:

image

关键挑战2:上述问题伴随而来的挑战是,为了能够精确的建模,建模工具必须能够建模负载、数据表征、电路能耗之间的数据关联性。为了尽可能光联系的空间,工具必须足够灵活(对于各种不同的用户定义电路)。

不幸的是,Timeloop+Accelergy和MNSim使用不准确的固定能耗和固定功耗模型,并没有建模数据关联性

此外,协同设计不同的层次意味着一个巨大的设计空间,并且设计点随着设计决策的数量的增加而指数增大。对于每一个点,我们都需要映射一个可能有着数百层的深度神经网络,且每一层都要搜索数千次的映射。

关键挑战3:快速建模对于探索巨大的设计空间非常重要。然而,对于精确建模,这个目标很困难,因为准确的建模需要对电路传播的许多数据值进行建模。

不幸的是,这一困难导致之前的工作只能在精确和快速中取其一,而无法同时达到。NeuroSim采用精确的数值关联性模型,但是它需要仿真每一个数据值,因此很慢。Timeloop+Accelergy和MNSim使用快速的固定能耗和固定功耗模型,但这些模型无法捕捉数据关联性。

这段背景与动机分析主要介绍了CiMLoop面临的一些挑战,以及作者们从中提炼出的动机。首先是灵活性方面,作者们认知到了当前的事实是CiM的电路拓扑五花八门,所以想要公平的进行比较,根本无法依赖一个简单的通用拓扑,只能给用户提供描述组件的能力,这是之前的NeuroSim和MNSIM都没有做到的事情。接着,作者们认知到了估计电路功耗时,数据值其实有很大的影响性,但之前的Timeloop+Accelergy和MNSIM都没有考虑这一问题,直接使用了非常简化的固定能耗和功耗模型,这是很致命的,所以他们决定要做能够考虑数据关联性的精确模型。最后,虽然NeuroSim也考虑到了数据关联性并且能够精确建模,但其会仿真具体的数据值,导致了其速度慢的问题,所以怎么做一个既能精确,但又不需要仿真每个具体值进而导致速度缓慢是CiMLoop需要解决的一个重要问题。

CiMLoop

在这一章节,作者们描述了CiMLoop以及其如何解决之前描述的三个关键问题。他们从CiMLoop的基础开始,然后描述了CiMLoop的的灵活的预组件数据重用模型与CiMLoop的系统表征。随后描述了CiMLoop的数据值关联性能耗模型与提供的组件模型。最后会讨论为什么CiMLoop是快速的。

首先是CiMLoop的基础,CiMLoop是基于Timeloop+Accelergy构建的。用户将系统通过一系列YAML文件进行描述(包括架构,工作负载,组件以及配置)并通过Python接口来运行。Accelergy执行系统中每个组件的面积/能耗估计。Timeloop利用这些估计执行映射搜索(空间/时间切片)并建模全系统的能耗,吞吐,以及面积。CiMLoop修改了Accelergy和Timeloop以支持CiM的特点,引入了支持数据值依赖性的组件建模接口以及电路级数据移动/重用/映射的支持。CiMLoop也引入了一个新的灵活的架构指定与快速建模管线。

CiMLoop的灵活指定方式使得用户可以指定组件在系统中的位置以及它们如何移动和重用数据。CiMLoop将组件定义为任意可能移动或重用数据的东西。组件可以是细粒度的(例如一个SRAM位单元)或者粗粒度的(例如一个SRAM缓存)。

  1. 预组件数据移动与重用:

    在数据搬运层级中,如果在一次访问X的父类时,组件X会多次使用数据,那么就认为组件X对一片数据会进行重用。重用仅在硬件支持,负载中存在(多次计算使用相同的数据),以及映射中存在(计算映射到相邻空间的组件或时间步,因此重用可以在组件或时间步之间发生)。

    对于每个组件和每个张量(例如输入,输出,权重),用户可以独立的设置支持的重用。时间重用可以在周期间保存数据,例如缓存暂时的重用数据。非时间重用不允许在周期之间做重用。非时间重用组件可能会也可能不会合并,这意味着将相同值的多个访问更改为一个后级存储访问。例如,当一个加法器将几个值加和时,它会把它们合并为一个输出(例如,重用多个加法的输出)。另一方面,一个DAC可能不会有合并。如果相同的值从一个DAC中数次输出传播,它必须从后级存储中取若干次。如果有机会,时间重用组件总是可以合并的。此外,数据可能会绕过组件周围的数据,而不会激活该组件(例如,输入绕过权重缓冲区)。

    在组件之间的空间上,数据可以重复使用(组件之间的多播或规约)或不重复使用(单独单播到每个组件)。例如,在基础CiM拓扑中,输出在行之间重复使用(即多行的输出由ADC求和并读取一次),但不在列之间重复使用(即每列的输出由DAC单独读取)。在下一节中描述CiM时,我们将展示这些重用选项中的每一个。

  2. 通过容器层级来表征系统:

    CiMLoop使用容器层级表征来实现可缩放的电路与架构表征。一个容器是一组组件与/或一组亚组件,而一个容器层级是一系列容器,其中每个都包含了所有的下级组件/容器。容器层级对于CiM系统的描述非常有用,因为:

    • 每个容器隔离了本地的设计决策,并抽象了其他容器。这使得描述有着许多不同类型组件的复杂设计变得容易。
    • 容器层级将电路和架构在统一层级继续宁描述,所以它们可以兼容对于存储层级的工具和抽象。
    • 容器层级可以嵌套到任意的深度(例如可以同时表述存储单元,电路,架构以及多芯片数据移动)
    • 多容器层级可以混合和匹配来辅助设计空间探索(例如用户可以创建一个宏单元,并在多个系统中对其进行测试)

    为了展示如何使用容器层级,作者们使用其描述了一个下图所示的CiM系统:

image

这个CiM系统与最初展示的CiM类似,但作者们增加了一个数字加法器来重用(求和)ADC的输出,并使用一个单独的缓存作为存储层级。在作者们的描述中,每个组件标注了下划线,且每个重用选项进行了加粗,CiM的描述如下:

  1. 一个抽象了CiM的容器,将其与其余的系统隔离。该CiM与一个缓存通信,并时间重用其输入与输出(一直存储其值)
  2. 在CiM中,输入传播通过一个非时间重用非合并DAC池转换为模拟量。与此同时,一个非时间重用加法器将从列出来的值进行求和,并将它们合并为一个输出。最终,作者们将阵列抽象为两个列容器。输入,而非输出,在两个列中空间重用(例如,所有的列都接收相同的输入,但每个列产生独立的输出)。
  3. 在每个列中,两个存储单元时间重用(在多个时间存储同样的值)权重。每个存储单元的输出空间(求和)重用然后穿过一个非时间重用非合并ADC转换为数字。

下图展示了一个该CiM简化后的YAML指定。给定该指定方式和负载后,CiMLoop会把负载映射(时空调度)到系统上,并产生面积/能耗/吞吐的估计。在完整的(非简化版)指定中,每个组件包含了一个类(例如一个缓存是SRAM),属性(例如ADC的方便率),一个可选的约束/启发用于映射搜索。CiMLoop 教程包括完整的语法。

image

  1. 精确的数据值依赖性建模:

    1. 数据值依赖性管线:为了建模数据值依赖的能耗,CiMLoop需要知道每个组件传播什么数据值以及它们如何影响能耗。这一过程被分为三步:
      • 负载操作数分布:对于每个负载张量(输入,输出,权重),CiMLoop使用该张量中的值的分布。相比于完整的张量,分布在建模中使用起来更为快速。
      • 编码与切片:CiMLoop计算每个组件的每个张量中元素的表示形式(表示形式可能会随着数据在系统中的移动而改变)。表示形式首先取决于编码,即将作数表示为二进制值。CiMLoop 支持来自CiM实现的编码和切片函数,包括偏移、差分、XNOR和仅幅度。并可以定义或导入其他编码方案。编码后,二进制值将被切片,这意味着它们的位被跨硬件组件分区。跨多个切分的计算暴露给 Timeloop映射器,让CiMLoop切分和空间/时间映射每个张量的位。
      • 组件能耗建模:在这个点,CiMLoop有了每个组件传播的编码和切片数据值的分布。每个组件模型使用这些分布来计算能量。每个组件可能不同地使用分布(例如,电阻器能量随着施加电压的持续时间而增加,而电容器能量随着施加电压的开关量而增加)。
    2. 提供模型:CiMLoop包括一套提供的插件,允许用户在自己的系统中对组件进行建模。CiMLoop使用 Accelergy插件套件,包括CACTI插件建模缓冲区和Aladdin插件建模数字组件。CiMLoop还包括一个简单的插件界面,允许用户定义新的依赖于数据值的能耗模型。为了对CiM组件进行建模,CiMLoop包括以下附加插件。
      • ADC插件:使用基于已发表的ADC的回归模型来预测一个满足用户定义的吞吐率、分辨率与数量的ADC(或一个ADC池)的面积与能耗。
      • NeuroSim插件:使用NeuroSim对阵列行/列驱动器和ADC;存储单元;数字元器件例如加法器、多路复用器和逻辑门进行建模。CiMLoop为了实现灵活性,将 NeuroSim 组件彼此分离,以便它们可以重新组装到用户定义的系统中。为了实现快速建模,CiMLoop将NeuroSim插件连接到第下一节中描述的快速建模管道。这些变化保持了高准确性,并在第后续章节中对其进行了量化评估。CiMLoop还将NeuroSim插件连接到 NVMExplorer存储单元探索工具中的存储单元,让用户可以灵活地交换器件模型。
      • 库插件:对各种CiM工作中使用的组件库进行建模。库插件可用于快速利用现成的组件模型创建新系统,或者它可以通过同时使用一组通用的组件,用于公平地比较不同的架构。
  2. 快速建模:

    为了可以快速建模,CiMLoop计算每种组件每次操作的平均能耗。该平均很好可以虽有应用于该种组件的任意数量的操作,使得CiMLoop可以在固定时间内建模任意数量的组件/操作。这对于快速建模CiM系统非常有帮助,使得任意组件可以并行(例如一个阵列中的数千个存储单元)。

    1. 通过分布建模深度神经网络操作:CiMLoop利用深度神经网络的分布(即每个张量的概率分布函数)作为其统计模型的输入。如之前所述,CiMLoop会利用这些分布以及它们的硬件表征来判断每种组件会传播的数据值。

      CiMLoop将深度神经网络的操作数分布于系统建模解耦是出于以下两个原因:

      • 使得CiMLoop的设计空间探索变得快速许多,因为深度神经网络不需要在每个CiM设计上实际运行
      • 其允许用户在分布的准确度与获取分布所需的用户工作量之间进行权衡,从而允许进行多准确度建模。用户可以向CiMLoop提供易于获取但准确度低的方式(例如,ReRAM器件模型的输入电压为 0V至1V的均匀分布);中等易得性和中等准确度(例如,二进制补码编码深度神经网络输入张量,并将结果分布用作ReRAM器件输入电压);或难以获得但高准确度(例如,模拟DAC生成模拟电压,并将结果分布用作ReRAM器件输入电压)。

      CiMLoop 假定单独张量中的值分布是独立的。利用这一假设,CiMLoop 为每个张量存储一个独立的分布。独立分布(而不是联合分布)更容易记录和用于能耗估计,因为对于\(N\)点概率密度函数和\(T\)个张量,独立分布必须存储的点数与\(O(NT)\) 成比例,而联合分布是$ O(N^T)$。但需要注意到,此限制不是CiMLoop 的基础,用户定义的模型可以使用联合分布。然而使用联合分配会使 CiMLoop 变慢,并且作者们实验发现独立分布已经足以获得高准确度。

    2. 预网络层建模:对于每个神经网络层,每个组件的插件模型会接收到数据值的分布(每个张量一个分布)并计算平均每次操作的男号。不同的层需要不同的预层次能耗,因为数据值分布可能会在不同的层次之间,以及同一层次的不同张量之间改变。

    3. 映射不变能耗:CiMLoop假定对于每个组件来说每个操作的能耗都是映射不变的(即其在不同映射之间不发生变化)。注意整体的组件能耗并不是映射不变的,因为每个组件的操作数量取决于映射(例如在不同的映射中,读取一次缓存的能耗是一样的,但是读取的数量,以及整体的能耗会不同)。

      如果映射不会影响为任何特定张量传播的值的分布,则此假设是有效的。通常,对于常规映射(即那些可以用循环嵌套表示的映射)来说就是这种情况,因为映射对张量元素的影响相同(例如,如果映射导致DAC传播输入的频率是原来的两倍,然后每个输入元素的传播频率是原来的两倍,并且分布不会改变)。但对于可能跳过零元素的稀疏系统,这一假设被违反了,但CiMLoop专注于密集的 CiM 系统建模。

      基于这一假设,CiMLoop预计算每个组件的每次操作的平均能耗,将计算时间摊销到多个映射上。

  3. 数据值依赖性计算的例子

    作为一个例子,这里将计算ReRAM器件读取所消耗的数据值相关能耗,其能耗\(E\)是权重电导\(G\)、施加的输入电压\(V\)的平方和读取持续时间\(T_{read}\)的乘积。

    下面的算法展示了在架构的设计空间探索中执行的计算。对于每个深度神经网络层(第 2 行),分析深度神经网络以获取输入值和权重值的概率分布函数(第 3 行)。然后,对于探索中的每个架构(第 4 行),第 5 行和第 6 行计算架构将用于表示输入和权重的平均平方电压和平均电导。这使用了前文中定义的架构的切片和编码功能(例如,架构可以将作数编码为2的补码值,并将该值表示为0V和1V之间的电压)。为简单起见,我们不显示切片(即跨多个组件和/或时间步长对位进行分区)。通过切片,算法将找到所有切片的平均能耗。

    最后,在第7行计算 ReRAM 的平均读取能耗。接下来,第 8 行和第 9 行迭代不同的映射和计算每个映射读取ReRAM器件的次数。第 10 行将读取次数乘以平均值读取能耗获得总的ReRAM读取能耗。

    数据值相关的计算时间的摊销是CiMLoop速度的关键。计算数据值相关能耗和分析深度神经网络消耗的开销可以忽略不计,因为与数据值相关的计算(第 5-7 行)在最内层的循环(第 8 行)上摊销,该循环可能会运行数千个映射,而分析 DNN(第 3 行)是摊销在最里面的(第 4 行)和中间的(第 8 行)循环上。每个映射的评估(第 9 行)是非数据值依赖性的,并且在大多数勘探中主导运行时间。

image

该算法计算设计空间探索中的数据值依赖性ReRAM能耗。能耗\(GV^2T_{Read}\)是电导,平方电压和读取时间的乘积。\(P_I(x)\)\(P_W(y)\)是输入和权重的概率分布函数。\(V_I(Arch,x)\)\(G_W(Arch,y)\)​将输入和权重值编码为电压和电导。

这个章节讨论了CiMLoop的具体技术细节,对于后续实现很有参考意义。首先是基于Container实现一个跨层次的统一建模工具,这一思路非常的简洁漂亮。Container是一组Component/Container的组合,在描述时可以把Container放到和其他的Component一个层级,再配合以YAML的描述方式,实现了一套便利的跨层级建模方式;其次是准确性方面,其实这一准确性需要与快速性相结合来讨论,因为实际上CiMLoop论准确性,并不能高于NeuroSim之类的建模每个组件的每次详细操作的仿真器类型工作(甚至在后续的评估过程中,NeuroSim是作为基准来使用的),其准确性是建立在与Timeloop+Accelergy和MNSIM这种使用固定能耗/功耗模型的对比上的,其主要的方式就是考虑了数据值依赖性,创造性的将张量的分布作为入参,通过统计模型来分析功耗。这种统计模型虽然无法超越NeuroSim类的仿真器的准确度,但在速度上会有非常大的优势,实际上来看CiMLoop的主要运行时间集中在评估不同映射方式的能耗上,而不是通过输入和权重的分布计算数据值依赖性的平均功耗上。

准确度与速度评估

在这一章节,作者们评估CiMLoop相对于之前CiM建模工作的准确度和速度。作者们使用NeuroSim作为基线。注意CiMLoop使用了NeuroSim插件,因此任何精度或者速度的差异来源于CiMLoop的数据值依赖性和快速建模管线。作者们使用ResNet18和ImageNet进行测试。其他的NeuroSim提供的模型使用CIFAR-10数据集,对于现代大型深度网络没有太多应用价值。

  1. CiMLoop准确性

    为了评估CiMLop的统计数据值依赖性模型的准确性,作者们建模了默认参数的NeuroSimCiM。NeuroSim计算每个建模组件传播的每个数据值,用于作为参考标准。作者们比较了以下两种情况:

    • CiMLoop使用深度神经网络每一层的输入,输出与权重分布,做如之前所述的数据值依赖性统计分析
    • 非数据值依赖使用固定能耗模型,此处乐观地假设能量是使用所有层的平均数据值计算的。通常,固定能量模型不会包含任何深度神经网络的信息

    下图比较了这两种不同设置在衡量整个CiM在ResNet18不同层的能耗的准确度。相对于NeuroSim的参考值,CiMLoop的数据值依赖性模型达到了平均误差3%,最大误差7%,而固定能耗模型的平均误差28%,最大误差70%。固定能耗模型错误更大的主要原因是其并没有建模输入,输出与权重的分布,而这些分布会随着深度神经网络层变化,并且对于模拟组件的能耗有着很大的影响。CiMLoop的数据值依赖性模型则考虑了这些分布的影响,从而减小了误差。CiMLoop剩余的误差来自于统计模型的误差,因为使用了独立分布表示每个深度神经网络层中的张量值。

image

  1. CiMLoop速度

    作者们比较了在默认的NeuroSimCiM上运行ResNet18/ImageNet时,CiMLoop和NeuroSim的建模速度。测试在Intel Xeon Gold 6444Y处理器上进行。对于CiMLoop,作者们评估了单核和16核的性能,运行了单个/5000个映射的情况。NeuroSim不支持多线程或者同时测试多个映射探索,因此其只进行了单核和单个映射的运行。

    下表展示了对比结果,CiMLoop相比于NeuroSim提升了几个数量级的建模速度。对于多个映射,每个映射消耗的时间会减少,因为 CiMLoop 可以分摊库调用、中间文件生成和数据值相关能耗建模的一次性启动成本。在大多数探索中,每个系统测试了数千个映射,而启动时消耗的运行时间几乎可以忽略不计。

image

CiMLoop 的速度优势会随着系统的增大和/或更大的深度神经网络工作负载而增加,因为 NeuroSim将模拟其他组件和/或操作,而 CiMLoop 统计模型的运行时将不会增加。CiMLoop 还优化了Timeloop+Accelergy 的建模速度,使CiMLoop成为目前对比下来最快的建模工具。

这个章节通过简单的实验,以NeuroSim为基线,评估了CiMLoop的准确性与速度,总体看下来,CiMLoop引入数据值依赖性对于准确性的提升非常显著,同时在速度上具备非常明显的优势,这一优势在更大的系统和/或更大的负载上还可以进一步放大。这一比较&评估方式是可以学习参考的。

案例分析:基于已发布的CiM

为了验证CiMLoop并提供一些CiMLoop可以探索的设计决策的例子,作者们提供了四个近期发表的流片的CiM。每个CiM包含了多个贡献,但由于篇幅限制,这里只讨论对于验证CiMLoop结果必要的部分。作者们鼓励读者阅读这些CiM的作者发表的文章,以及他们为每个CiM搭建的开源模型。

对于每个CiM,使用NeuroSim插件建模阵列与行/列驱动。作者们创建存储单元模型,并校准每个组件的面积/能耗以匹配发表的值。除非特殊说明,否则所有的数据流都是权重静止的,即权重预填充到CiM的CiM阵列中,输入送入到CiM阵列中,输出从CiM阵列中读出。下表展示了每个CiM的参数属性。CiMLoop可以建模不同工艺节点、位精度、器件工艺的系统。对于输入的深度神经网络负载,这里分别使用ImageNet和Wikipedia用于图像与语言模型。

image

  1. 验证CiMLoop

    在本节中,作者们通过对公开发表的CiMA-D建模来验证CiMLoop。他们将CiMLoop的建模结果与每个CiM公开数据进行比较,包含了仿真与硅验证的结果。对于接下来的每个点,包含了作者们能够找到可找到公开数据的CiM(例如,CiMA/B/D的论文中有电压扫描结果,但C没有)。为了便于可视化,作者们展示使用所有测量数据(包含了图中没有包含的数据)的平均值误差测量。

    1. 能耗/吞吐率与供电电压

      下图展示了CiMLoop建模CiMA/B/D不同电压下能耗与吞吐的的情况。CiMB的能耗是数据值关联的,因此此处展示了对于小的和大的数据值的结果。对于供电电压扫描,CiMLoop的平均能效与吞吐率误差为7%和2%。

image

  1. 能耗/吞吐率与输入编码

    下图展示了CiMLoop建模CiMB/C的能耗与吞吐在不同的输入比特数的情况。对于这些扫描,CiMLoop的能效与吞吐率误差为6%和5%。

image

  1. 能耗分解

    下图展示了CiMLoop建模CiMC和D的能耗分解。对于CiMC,此处报告了1b,2b和8b输入下的能耗情况,用于展示CiMLoop可以捕捉到每个组件随着输入比特数变化而缩放的能力。CiMD中,由于没有对组件进行建模,杂项能量低于参考值;可以通过向模型添加更多组件来提高准确性(因为模型是用户定义的,并且可以轻松添加组件)。对于分立元件,CiMLoop 的平均能量误差为 4%。

image

  1. 面积分解

    下图展示了CiMLoop建模的CiMA/B/C/D的面积分解。与能量分解一样,建模的CiMD的杂项面积可以是通过对组件进行建模而变得更加精确。对于分立元件,CiMLoop 的平均面积误差为 8%。

image

  1. 数据值依赖能耗

    下图展示了CiMLoop建模CiMB的数据值依赖性能耗。随着MAC平均值的增大,CiMB的DAC开关的更频繁以提供更大的输入值,其模拟加法器也使用更大的模拟值进行充放电。这些数据值依赖性的影响可以将CiM的能量放大2.3倍。

image

  1. 使用CiMLoop进行探索

    在这一节,作者们讨论了CiMLoop的可用性。它们使用CiM技术栈的其中一层,分别比较了CiMA-C,并通过CiMD建模了完整系统。最终,他们还进行了一个跨CiM比较。

    1. 映射

      CiMA在相邻的CiM阵列的列之间重复使用输出,而不是输入。在每个\(N\)个列之间重用列会增加输出重用\(N×\)倍,但减少输入重用\(N×\)倍。这会影响模数/DAC的能耗。更多的输出重用可以减少ADC的转换次数和能耗,但代价是输入重用的减少会增加DAC转换和能耗。这一设计决策还会改变可用的映射。如果相邻的列重用输出,那么必须映射工作负载作以在这些列之间共享输(即将一个输出通道映射到这些列)。否则,阵列无法得到充分利用。

      下图中探索了CiMA在不同数量的列中复用输出的配置。分别运行最大利用率(矩阵向量乘与阵列的维度匹配)和变化利用率 (ResNet18) 工作负载。然后报告模数,DAC和其他组件的能耗。对于利用率最高的工作负载,增加输出重用会降低ADC的能耗,但会有导致更高的DAC能量。对于可变利用率工作负载,三列重用配置比其他配置具有更低的能耗。这是因为ResNet18使用了许多3×3卷积核,并且他们能够在三列重用上实现高利用率映射。这也是 Jia 等人在他们制造的芯片中使用三列重用的原因之一。

image

  1. 电路

    CiMB使用模拟加法器电路,该电路对模拟输出求和。ADC读取结果和,而不是独立读取每个输出,因此模拟加法器可以减少ADC的使用次数。这个加法器带有一个约束,即它的输入必须来自不同的权重位。

    在下图中,作者们探索了不同宽度的模拟加法器(1、2、4 和8个数)和具有不同权重的位数的负载。求和更多模拟值的加法器可以提高面积的吞吐量,因为它们会减少读取输出所需的ADC数量。然而,当每个权重的位数较少时,模拟加法器变得未充分利用。较大的加法器也占用更多的芯片面积。因此,具有8个数输入的加法器的CiM一直不具有最高的吞吐量。

image

  1. 架构

    使用CiMC,作者们对不同阵列大小进行了架构探索。他们分别将阵列行数和列数设为 64, 128, 256, 512,或 1024 并测试最大利用率(矩阵向量乘法)、大张量大小(Vision Transformer ViT)、中等张量大小(ResNet18) 和 小张量大小(MobileNetV3)工作负载。

    如下图所示,随着阵列尺寸的增加,由于更多的MAC摊销ADC和数字输出总和能量,能量会减少。该效果对于最大利用率和大型张量大小的工作负载来说是最强的。对于中等张量大小的工作负载,随着阵列变大,效果会达到饱和,并且对于较小的层来说会无法得到充分利用。对于小张量大小的工作负载,未充分利用会增加所有规模阵列的能耗,此时较小的阵列是能耗最低的选择。

image

  1. 全系统

    CiM系统通过减少片外数据移动并使用CiM阵列并行执行多个MAC来降低能耗。为了探索这些技术点对于全系统的贡献,作者们将CiM放在一个完整的系统中。该系统包括一个DRAM后级存储和一个芯片,该芯片具有带有输入/输出缓冲区的并行CiM、路由器和一个全局缓冲区。片上存储器可以容纳任何经过测试的神经网络层,因此每一层的输入/输出/权重将仅仅在DRAM之间往返一次。

    张量大小会影响执行的MAC数量,因此作者们测试了大张量(大型语言模型 GPT-2)和混合大小张量(ResNet18)工作负载。他们比较了三种情况:(1) 输入/输出/权重存储在片外DRAM,并且每一层都要进行独立获取;(2) 从DRAM获取输入/输出,权重固定(每层预加载);(3) 权重固定,输入/输出保存在片上的全局缓冲区中。

    下图展示了片上数据移动、片上全局缓冲器和片外数据移动的系统能量分解。我们看到,由于权重获取较少,当从片外权重变为权重固定时,总能量显著降低。然而,从片外获取输入/输出的好处是有限的。回想一下,该系统每层只向 DRAM 传输一次输入/输出;为了获得更多好处,必须避免将输入/输出转移到片外层间。我们注意到,权重固定的CiM需要足够的内存从而在片上保留所有深度神经网络权重。要存储大型深度神经网络,这可能需要多芯片管线或高密度存储技术。

image

  1. 跨CiM

    CiMLoop可用于预测CiM扩展到新的工艺节点的效果,并在不同的CiM之间进行公平的比较。我们比较了三个基于SRAM的CiMA/B/D,使用CiMB存储单元和8b ADC将所有CiM缩放到7nm。

    下图比较了三个CiM在不同的输入与权重位下的能效。CiMA通过模拟计算1b的输入/权重MAC,并通过数字进行累加。这使得CiMA可以利用灵活的利用较少位数的比特的输入/权重来提升能效,但这个策略对于更多比特的输入/权重是比较低效的。而存算宏B/D使用4比特/8比特的模拟组件,则可以增加输出重用并减少ADC能耗。然而,这些组件在较少位数输入/权重时无法充分利用,因此在较少比特的操作时,CiMB/D的能效增益很小。

image

这一节主要是做了CiMLoop的评估工作,对于CiMLoop的能效,吞吐率,能耗分解,面积分解以及数据依赖性能耗的准确性,通过对公开发表的CiM进行建模和评估,再与发表论文中的数据进行对比来实现验证,总体来说CiMLoop展现出了高的准确性。随后,还展现了CiMLoop在不同的层级中进行设计空间探索的应用,例如用于分析映射、电路、架构、全系统,以及做多个CiM之间的能效比对。整体上来说,这一评估方法值得借鉴,同时对于CiMLoop以及类似的建模/仿真器工作的应用场景有了数个展示。

关联工作

除了之前讨论过的工作,还有许多工作探索了CiM的不同部分。CiMLoop建模了面积/能耗/吞吐,IBM AI Hardware Kit,CrossSim和MemTorch建模了神经网络的准确度。Eva-CiM建模了CPU/CiM的接口但没有建模CiM。Simeuro和SuperNeuro建模了脉冲神经网络(而非深度神经网络)。PUMA提供了一个特定的神经网络系统的详细建模,但是没有探索设计空间。Sparseloop和CiMLoop类似,使用统计分析模型,将其应用到建模稀疏神经网络系统中。

ZigZag-IMC的工作实现了可参数化的CiM模型与灵活的架构指定。非参数化的改动(例如增加或减少组件,改变组件的连接)需要通过修改仿真器源码。这与CiMLoop不同,其支持通过仅仅改动输入指定而非修改仿真器源码就可以实现非参数化的改动。

这里介绍了大量的关联工作,除了之前介绍过的NeuroSim,MNSIM,Timeloop+Accelergy等代表性工作,还包括了IBM AI Hardware Kit,CrossSIM,MemTorch,Eva-CiM,Simeuro,SuperNeuro,PUMA,Sparseloop,ZigZag-IMC等,需要后面对这些工作进行广泛的调研和综述性的总结。

结论

在这篇论文中,作者们提出了CiMLoop:一个灵活的,准确的,快速的建模工具,将所有的CiM技术栈进行连接。CiMLoop让研究者们可以在每个层级评估设计决策,跨层级协同优化,以及公平的比较CiM实现。通过将所有的层级带入到同一个模型中,CiMLoop可以为器件,电路和架构研究社区建立桥梁。CiMLoop甚至可以用于超越CiM的领域来建模传统加速器,以及一些其他原理的加速器,例如光子加速器。作者们希望研究者们使用CiMLoop来分享他们的工作,发布开源模型,以及通过所有社区的贡献来发现新的洞察和协同设计机会。

总体来说,CiMLoop在跨层级建模的灵活性,数据值依赖性建模等方面具有很强大的领先性,值得学习。但也存在一些局限性,例如无法建模负载运行的准确度(因为它不考虑模拟计算的PVT干扰,以及器件的Variation等非理想因素),对数字CiM的探索有限,没有探究异构系统,无法研究硬件稀疏性等,此外由于是建模(Modeling)工作,而非仿真器(Simulator)工作,实际上无法在CiMLoop上进行软件栈的功能/性能验证,因此无法分析软件效率(例如底层算子库开发,编译器开发等底层软件开发的性能分析)。总体来说,建模与仿真是两个侧重点,建模更重视快速性以便于前期的设计空间探索、而仿真更多的作为集成在软硬件开发中的一环,但如果想要实现真正的存算全技术栈的上下贯通,仿真的意义会更大一些。但仿真的速度因为需要模拟具体行为而受到限制,因此一个思想是可以结合建模与仿真各自的优势,以仿真为主体,针对一些会造成瓶颈的环节使用建模的方式进行评估,这或许会是一个有趣的思路。

posted @ 2025-04-14 18:56  sasasatori  阅读(441)  评论(0)    收藏  举报