Page 83 - 《软件学报》2021年第6期
P. 83

苏卓  等:基于分支标记的数据流模型的代码生成方法                                                        1657


         支情况的模型实例,然后将这些实例按照本文提出的算法最终转化为 C 语言代码.实验所构建的 Ptolemy-II 模
         型如表 2 中的第 1 列所示,对应生成的代码如第 2 列所示.这 3 个模型都使用离散事件指示器(DE director)和离
         散时钟(DiscreteClock)来驱动,模型的仿真时间为 50 个单位时间,离散时钟的采样时间为 1 个单位时间,所以整
         个模型会反复执行 51 次.模型中的 BooleanSwitch 组件为二分支的分支组件,它会根据它最下面的端口数据的
         逻辑值选择将左边输入数据传递到右边的哪个端口.Ramp 组件可以产生等差数列,这里我们设置的等差数列首
         项为−25,公差为 1,该组件每次输出的结构会从−25 开始依次加 1.Expression 为表达式组件,可以把输入数据代
         入表达式求解,再将结果传递到输出端口.Scale 组件可以将输入数值缩放后输出.SequencePlotter 示波器组件可
         以将每次输入的数据以折线的形式绘制出来.Counter 组件的输出从 1 开始,之后每次执行输出会增加 1.Display
         组件可以将输入数据以文本的形式输出出来.表 2 中第 2 列显示的代码只是完整代码的一部分,这里只把组件
         的调度及计算逻辑相关的代码呈现了出来,其他的比如主函数封装、局部变量的声明等和调度无关的代码在这
         里不加以展示.另外,我们以标准输出“printf”作为各种输出组件对应的生成代码;并且在由 CGLT 转化为代码的
         过程中,以 BooleanSwitch 组件为数据源的组件,直接跨过 BooleanSwitch 组件向前寻找数据源.通过这种方式,可
         以生成更精简的代码.

                             Table 2    Model examples for three different branch situations
                                       表 2  3 种不同分支情况的模型实例
                                模型                                     对应的 C 代码
                                                          1.   Ramp_output+=1;
                                                          2.   Expression_output=Ramp_output>0;
                                                          3.   if (Expression_output){
                                                          4.     printf(“%f\n”,Ramp_output);
                                                          5.   } else {
                                                          6.     Scale_out=Ramp_output*0.1;
                         (a)  分支合并情况的模型                   7.     printf(“%f\n”,Scale_out);
                                                          8.   }
                                                          1.   Ramp_output+=1;
                                                          2.   Expression_output=Ramp_output>0;
                                                          3.   Expression2_output=Ramp_output>−10;
                                                          4.   if (Expression_output){
                                                          5.     Expression3_output=Ramp_output*5+1;
                                                          6.     printf(“%f\n”,Expression3_output);
                                                          7.   } else {
                                                          8.     if (Expression2_output){
                                                          9.       Expression4_output=Ramp_output*−4+1;
                                                          10.      printf(“%f\n”,Expression4_output);
                                                          11.   } else {
                         (b)  分支嵌套情况的模型
                                                          12.      Expression5_output=Ramp_output*5+91;
                                                          13.      printf(“%f\n”,Expression5_output);
                                                          14.    }
                                                          15. }
                                                          1.   Counter_output+=1;
                                                          2.   Expression_output=Counter_output%7==0;
                                                          3.   Expression2_output=Counter_output%3==0;
                                                          4.   if (Expression_output && Expression2_output){
                                                          5.     printf(“%d%d\n”,Counter_output,Counter_output);
                                                          6.   } else if (Expression_output){
                                                          7.     printf(“%d\n”,Counter_output);
                                                          8.   } else if (Expression2_output){
                                                          9.     printf(“%d\n”,Counter_output);
                         (c)  分支交叉情况的模型
                                                          10. }
             表 2(a)模型显示了一个在深度学习领域中常用的激活函数 LeakyRelu 函数的图像:当 Ramp 组件的输出大
         于 0 时,SequencePlotter 显示 Ramp 组件本来的输出值;当 Ramp 组件的输出小于等于 0 时,SequencePlotter 显示
         Ramp 组件输出值乘以 0.1.模型中的 BooleanSwitch 组件生成了 if-else 语句(第 3 行和第 5 行);SequencePlotter
         组件合并了 BooleanSwitch 组件的两个分支,由于 SequencePlotter 组件在两个分支下的数据源不同,所以在 if 和
         else 控制的语句块下各生成了一行代码(第 4 行和第 7 行);Scale 组件仅在 BooleanSwitch 的 False 分支中,所以
   78   79   80   81   82   83   84   85   86   87   88