Page 382 - 《软件学报》2025年第10期
P. 382

杨乐 等: BIVM: 类脑计算编译框架及其原型研究                                                      4779


                 IR  由第  2  层  IR  的细粒度描述通过递降得到: 一方面, 需要将神经网络模拟过程中的具体计算操作转变为计算内
                 核执行的   GaBAN  指令集中的指令序列实现, 另一方面, 需要生成控制核心执行的硬件配置、驱动过程                       (见第  3.4.3 节).
                  3.4.1    CPU  后端
                    面向  CPU  后端的第   3  层  IR  大体延续了第  2  层  IR  的细粒度描述, 在存储、计算、控制流上描述          SNN  的计算
                 操作过程. 递降过程中, 一方面针对神经元组的空间并行性, 对神经元更新过程进行向量化优化; 针对                             SNN  的稀疏
                 特性, 实现了脉冲张量类型的存储与索引方式, 并对脉冲传播操作进行编译优化. 图                         3(d1) 展示了神经元更新过程
                 向量化与脉冲传播过程稀疏性优化后的结果.
                    ● 神经元更新操作的并行优化
                    同一个类脑计算应用内的神经元模型一般是一样的                   (参数可能不同), 即多个神经元的同一状态的计算类型是
                 一样的, 仅数据不同, 属于单指令流多数据流             (SIMD) 计算, 因此神经元更新过程中存在向量化优化空间: 第                3  层
                 IR  对神经元更新操作的计算过程进行拆解, 若将神经元组的内部状态看作几个一维张量, 则其计算过程可表示若
                 干逐元素的张量操作        (element-wise operation), 包括张量加法、减法、乘法等操作. 这些张量操作具有并行性, 针
                 对  CPU  后端可以采用    SIMD  指令集进行加速. 故利用 MLIR vector 方言      (一个用于描述向量化的数据结构方言)
                 声明更新过程中的并行计算. 图          3(d1) 的神经元更新操作中使用       vector.load  与  vector.store 对连续一段神经元的内
                 部状态进行访存, 并通过       arith  方言对  vector 数据类型进行计算, 这些指令会在后续递降过程中转化为具体硬件的
                 SIMD  指令.
                    ● 脉冲张量类型
                    脉冲张量类型描述了神经元的发放状态, 第               1、2  层  IR  主要负责描述与设计, 注重于数据类型的构建和方言
                 生态的完善. 第    3  层  IR  需要考虑脉冲张量的具体实现和优化策略, 即存储格式、操作的实现与优化.
                    脉冲张量采用      sparse tensor 方言描述存储. sparse tensor 针对不同的稀疏存储格式抽象出一套通用的编码方
                 法, 分别存储非零元素的下标和值. 对于脉冲张量, 可以直接存储非零值的下标而无需存储值                           (因为值必定为     1).
                    ● 脉冲传播操作的稀疏性优化
                    脉冲传播操作可以视作一类特殊的矩阵-向量乘法操作. 使用                    linalg.generic 操作可以对此过程进行描述, 但其
                 生成的计算内核无法充分利用发放状态与连接矩阵的稀疏性. 针对上述问题, 本文设计了利用两者稀疏性加速脉
                 冲传播操作的方法, 避免形如         x+0=x 以及  x×0=0  等不必要的计算.
                    图  3(d1) 的脉冲传播操作展示了优化的一种具体实现. 首先使用                sparse tensor 方言将连接矩阵  (%var1) 与发放
                 状态  (%var2) 转变为稀疏格式, 并通过      pointers、indices、values 操作获取内部状态, 方便下一步对非零元的索引
                 过程. 计算时则通过仅遍历发放状态的非零元                (访问  f_indice  变量) 与连接矩阵中的非零元来减少计算            (访问
                 w_pointer、w_indice、w_value 变量). 内层循环中进一步使用      vector 方言对计算过程进行      SIMD  向量化优化, 此
                 处需要使用    vector.gather 对结果向量中非零元对应下标的值进行不连续访存              (访问  a_in  变量).
                    需要指出的是, 挖掘稀疏性有多种方法, 而后续测试表明, 针对连接矩阵与发放状态的不同稀疏度, 不存在一
                 个“统一”的最优方法. BIVM      实现了不同格式的计算与加速方法, 用户可以在描述中通过附加属性来起到类似编
                 译指示   (directives) 的作用, 进而在第  3  层  IR  中会被转化为对应的实现.
                    ● 硬件执行
                    面向传统架构处理器, 第        3  层  IR  后续会被递降为  LLVM IR. LLVM IR  是一个通用的描述方式, 便于递降为
                 不同后端    (通常是通用处理器) 的可执行文件. 至此我们已经将原有的                  SNN  应用递降为一个不再包含        SNN  语义
                 而全部由基础操作构成的         IR. 通过后续的编译链接步骤, 可以得到最终的可执行文件.
                  3.4.2    ReRAM  后端
                    ReRAM  是一种被广泛应用的神经形态器件, 可利用其静态或者动态特性来高效仿真神经网络突触. 当前版本
                 的  BIVM  主要支持基于    ReRAM  静态特性的、以存内计算         (processing-in-memory) 形式完成的高效、高密度矩阵
                 向量乘运算. 具体而言, 对于       ReRAM  交叉开关结构中的每一行施加电压, 遵循欧姆定律和基尔霍夫定律, 该电压
                 和交叉点的电导值相乘得到电流, 每一列电流累加得到结果, 从而完成了一次模拟的矩阵向量乘法                               (详细说明请见
   377   378   379   380   381   382   383   384   385   386   387