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

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


                 结束后, 对于各个核     AM  中的数组以向量的形式循环执行计算, 将该核子数组规约到一个                    1 024 位宽的向量中    (图  8
                 中框内部分).

                 3.6.1.2    VPU  内规约
                    通过上述方法, 我们在       24  个  DSP  核上都得到了对应分区的规约结果并且保存在对应                VPU  的一个  VPE  上.
                 对于双精度    (double) 的数据, 可以直接使用    mov_from_svrX  接口, 将  VPE  中  16  个数卸载到  SVR  寄存器进行合并.
                 然而, 对于单精度浮点数, 由于        VPE  的最小访存单位为      64  位, 因此无法直接进行对应的操作. 同图         7  中的思路, 本
                 文先将取出来的      64  位解包成  2  个对应的单精度浮点数, 再进行合并.

                 3.6.1.3    DSP  簇核间规约
                    经过以上两步, 我们在       N  个计算核上分别得到了对应分段的规约结果, 保存为                N  个标量值. 进一步, 本文实现
                 了多核之间的数据规约算法. 由于核间的规约需要在核间交互数据, 而多核可共享的                          DDR  又是带宽受限的. 因此,
                 利用  GSM  缓存比    DDR  内存访存带宽更大的特性, 本文将子数组规约结果和核间规约的临时共享地址
                 shared_mem  都创建在所有核共享的      GSM  缓存中, 以减少对    DDR  的频繁访存.
                    具体来说, 本文将     DSP  簇中的不同核分成若干个子组, 每个子组内的计算核执行一定的归约操作                       (例如求和),
                 然后将子组的结果进行合并, 得到一个较小的结果集合. 然后再将较小的结果集合分成若干个子组, 重复上述操
                 作, 直到最终只剩下一个结果. 核间数据规约算法流程见算法                    3. 其中, core_num  代表本机规约使用的核心数,
                 shared_mem  是位于  GSM  的中间变量存储地址, warp_size 是常量, 一般为      32.
                 算法  3. 核间数据规约.

                 输入: core_num, sub_reduce, shared_mem, warp_size;
                 输出: sub_reduce.
                 1. FOR each core DO in parallel:
                 2.  int coreID = get_thread_id();
                 3.  FOR i = (warp_size >>1) TO 0 STEP >>=1 DO:
                 4.   shared_mem[coreID] = sub_reduce
                 5.   barrier;
                 6.   int temp = coreID+i<core_num?shared_mem[coreID+i] : 0;
                 7.   Reduce_op(sub_reduce, temp);
                 8.  END
                 9. END

                 3.6.2    基于规约的算子实现

                 3.6.2.1    sum  以及  softmax
                    基于上述的规约算法, 开发人员自然而然可以实现                 sum  算子. 对于  softmax  算子和  log_softmax  算子, 我们首
                 先给出其计算公式:

                                                    exp(x i − x max )
                                          
                                           σ SM (x i ) =
                                          
                                          
                                          
                                                    K ∑
                                          
                                                        (      )
                                          
                                          
                                                      exp x j − x max
                                          
                                          
                                          
                                                    j=1                                               (4)
                                          
                                          
                                          
                                                                           
                                                                K
                                          
                                                              ∑            
                                                                    (     )
                                                                           
                                                                           
                                           σ LSM (x i ) = (x i − x max )−log  exp x j − x max  
                                                                          
                                          
                                          
                                                                 j=1
                    区别于原始的      softmax  公式, 本文将  e 的指数减去所有输入的最大值, 缩放成小于等于             0  的数, 防止造成数值
                 溢出. 反向传播可由:
   478   479   480   481   482   483   484   485   486   487   488