Page 481 - 《软件学报》2025年第8期
P. 481

3904                                                       软件学报  2025  年第  36  卷第  8  期



                 11.    END
                 12.    vector_store(C[offset+i]) //将结果保存到  DDR;
                 13.   END
                 14. END
                    在算子中根据输入输出以及计算中间结果的大小, MaxVectorCount 可以取                  128, 256, 512  或  1024. 一个  VPE
                 中集成了    3  个浮点乘加计算单元, 为了充分利用处理器            VLIW  的性能, 在实现时要将加减操作          (a–b) 转换为乘加
                 和乘减   (a×1–b) 操作.
                    对于计算过程中的常数变量, 本文通过             Hthreads 的广播指令将其广播成      VPU  中的一个向量常量. 然而由于硬
                 件的特性, 存储器一次可处理的最低位宽为               64  位, 单个单精度数据并不支持广播. 本文使用            C  语言中的联合体
                 union  实现  32  位常数到  64  位的打包和解包, 它允许将多个不同类型的成员变量存储在同一个内存空间中. 一个
                 union  的长度为  64  位宽, 代表  1  个双精度浮点数或者长度为      2  的单精度浮点数组. 实现代码如图         7  所示.












                                                   图 7 单精度浮点数打包

                 3.5   激活函数及其反向传播算子实现
                    激活函数可以使模型更加稳定, 显著提高模型性能, 是深度神经网络中不可缺少的模块. 本文实现了语言模型
                 中最常用的两个激活函数.
                    ReLU  激活函数是一种常用的非线性函数, 其表达式为               y = max(x, 0), 具有计算速度快, 训练过程稳定的特点,
                 因此广泛运用在深度学习模型中. ReLU           前向传播和反向传播公式为:

                                                      ReLU (x) = max(0, x)
                                                                                                      (1)
                                                      dx = (y > 0) ? dy : 0
                    由于硬件位宽限制, 向量        C  接口的条件赋值语句仅支持双精度数据. 对于单精度下的                  ReLU  反向传播中的条
                 件赋值操作, 本文采用位运算实现          res = (A>B) ? C : D, 得益于  VLIW  的架构, 取得了明显的加速效果, 见算法     2.
                 算法  2. 基于位运算的条件赋值方法.

                 输入: A, B, C, D;
                 输出: res.
                 1. vo = gt(A, B);  //判断是否赋值
                 2. vzero = mov 0 to VPEs;  //构造全  0  向量
                 3. vot = sub(vo, vzero);  //条件向量格式化为全  0  或全  1
                 4. x64 = (lvector unsigned long int)C;
                 5. y64 = (lvector unsigned long int)D;
                 6. vo64 = (lvector unsigned long int)vot; //强制类型转换
                 7. //位运算赋值
   476   477   478   479   480   481   482   483   484   485   486