Main Content

优化全局变量使用

要调整应用程序并选择执行速度和内存使用量的折衷方案,您可以为生成的代码选择全局变量引用优化。

在“配置参数”对话框的优化全局数据访问下拉列表中,有三个参数选项控制全局变量使用优化。

  • 。使用默认优化。此选项适用于大多数模型。代码生成器会平衡局部变量和全局变量的使用。它生成用于平衡 RAM 和 ROM 消耗量与执行速度的代码。

  • 使用全局变量保存临时结果。重用全局变量可提高代码效率和可读性。这种优化会重用全局变量,从而使代码生成器定义更少的变量。它会减少 RAM 和 ROM 消耗量和数据副本数。

  • 最小化全局数据访问。使用局部变量来缓存全局数据可减小代码大小,从而减少 ROM 消耗量。这种优化可提高执行速度,因为代码对局部变量引用使用的指令少于对全局变量引用使用的指令。

    通过使用局部变量来尽量减少全局变量的使用与堆栈使用量控制相互影响。例如,堆栈大小可以决定代码生成器可在生成的代码中分配的局部和全局变量的数目。有关详细信息,请参阅Customize Stack Space Allocation

使用全局变量保存临时结果

当您选择 None 时,代码生成器使用全局和局部变量,而当您选择 Use global to hold temporary results 时,代码生成器使用全局变量。

示例模型

在模型 UseGlobalsForTemporaryResults 中,Assignment 模块将来自 Inport 模块和 Constant 模块的值赋给输出信号。输出信号馈入 Gain 模块中。

UseGlobalsForTemporaryResultsModel.png

model = 'UseGlobalsForTemporaryResults';
load_system('UseGlobalsForTemporaryResults')

生成代码但不进行优化

  1. 在“配置参数”对话框中,验证是否选择了信号存储重用参数。

  2. 在“配置参数”对话框中,对于优化全局数据访问参数,选择 None 或在 MATLAB® 命令行窗口中输入以下命令:

set_param('UseGlobalsForTemporaryResults','GlobalVariableUsage','None');

编译模型。

slbuild(model);
### Starting build procedure for: UseGlobalsForTemporaryResults
### Successful completion of build procedure for: UseGlobalsForTemporaryResults

Build Summary

Top model targets built:

Model                          Action                        Rebuild Reason                                    
===============================================================================================================
UseGlobalsForTemporaryResults  Code generated and compiled.  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 14.501s

查看生成的代码而不进行优化。这是 UseGlobalsForTemporaryResults.c 的一部分。

cfile = fullfile(pwd,'UseGlobalsForTemporaryResults_ert_rtw',...
    'UseGlobalsForTemporaryResults.c');
coder.example.extractLines(cfile,'/* Model step','/* Model initialize',1, 0);
/* Model step function */
void UseGlobalsForTemporaryResults_step(void)
{
  real_T rtb_Assignment[5];
  int32_T i;

  /* SignalConversion generated from: '<Root>/Assignment' incorporates:
   *  Constant: '<Root>/Constant'
   */
  for (i = 0; i < 5; i++) {
    rtb_Assignment[i] = rtCP_Constant_Value[i];
  }

  /* End of SignalConversion generated from: '<Root>/Assignment' */

  /* Assignment: '<Root>/Assignment' incorporates:
   *  Inport: '<Root>/In1'
   */
  rtb_Assignment[1] = rtU.In1;

  /* Outport: '<Root>/Out1' incorporates:
   *  Gain: '<Root>/Gain'
   */
  for (i = 0; i < 5; i++) {
    rtY.Out1[i] = 2.0 * rtb_Assignment[i];
  }

  /* End of Outport: '<Root>/Out1' */
}

该代码为本地向量 rtb_Assignment 赋值。最后一条语句将局部向量 rtb_Assignment 中的值复制到全局向量 rtY.Out1。更少的全局变量引用会提高执行速度。该代码对全局变量引用使用的指令多于对局部变量引用使用的指令。

在静态代码度量报告中,检查“全局变量”部分。

  1. 在“代码生成报告”窗口中,选择静态代码度量报告

  2. 向下滚动到 Global Variables 部分。

  3. 选择每个变量前的 [+] 符号以展开它。

对全局变量的读写总次数为 2。

生成代码并进行优化

在“配置参数”对话框中,对于优化全局数据访问参数,选择 Use global to hold temporary results 或在 MATLAB 命令行窗口中输入以下命令:

set_param('UseGlobalsForTemporaryResults',...
    'GlobalVariableUsage','Use global to hold temporary results');

编译模型。

slbuild(model);
### Starting build procedure for: UseGlobalsForTemporaryResults
### Successful completion of build procedure for: UseGlobalsForTemporaryResults

Build Summary

Top model targets built:

Model                          Action                        Rebuild Reason                   
==============================================================================================
UseGlobalsForTemporaryResults  Code generated and compiled.  Generated code was out of date.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 13.228s

查看优化后的生成代码。这是 UseGlobalsForTemporaryResults.c 的一部分。

cfile = fullfile(pwd,'UseGlobalsForTemporaryResults_ert_rtw',...
    'UseGlobalsForTemporaryResults.c');
coder.example.extractLines(cfile,'/* Model step','/* Model initialize',1, 0);
/* Model step function */
void UseGlobalsForTemporaryResults_step(void)
{
  int32_T i;

  /* SignalConversion generated from: '<Root>/Assignment' incorporates:
   *  Assignment: '<Root>/Assignment'
   *  Constant: '<Root>/Constant'
   */
  for (i = 0; i < 5; i++) {
    rtY.Out1[i] = rtCP_Constant_Value[i];
  }

  /* End of SignalConversion generated from: '<Root>/Assignment' */

  /* Assignment: '<Root>/Assignment' incorporates:
   *  Inport: '<Root>/In1'
   */
  rtY.Out1[1] = rtU.In1;

  /* Outport: '<Root>/Out1' incorporates:
   *  Assignment: '<Root>/Assignment'
   *  Gain: '<Root>/Gain'
   */
  for (i = 0; i < 5; i++) {
    rtY.Out1[i] *= 2.0;
  }

  /* End of Outport: '<Root>/Out1' */
}

该代码在不使用局部变量的情况下为全局向量 rtY.Out1 赋值。这种赋值可改善 ROM 和 RAM 消耗量,减少数据副本数。代码将值置于每个赋值运算的目标变量中,而不是在最后复制值。在静态代码度量报告中,检查“全局变量”部分。

由于使用全局变量保存局部结果,全局变量的读写总次数从 2 增加到 5。这种优化通过重用全局变量来减少数据副本数。

关闭代码生成报告。

最小化全局数据访问

生成读写全局变量频率较低的优化代码。

示例模型

在模型 MinimizeGlobalDataAccess 中,五个信号馈入 Multiport Switch 模块。

model = 'MinimizeGlobalDataAccess';
load_system('MinimizeGlobalDataAccess.slx')

MinimizeGlobalDataAccessModel.png

生成代码但不进行优化

  1. 在“配置参数”对话框中,验证是否选择了信号存储重用参数。

  2. 在“配置参数”对话框中,对于优化全局数据访问参数,选择 None 或在 MATLAB® 命令行窗口中输入以下命令:

set_param('MinimizeGlobalDataAccess','GlobalVariableUsage','None');

编译模型。

slbuild(model);
### Starting build procedure for: MinimizeGlobalDataAccess
### Successful completion of build procedure for: MinimizeGlobalDataAccess

Build Summary

Top model targets built:

Model                     Action                        Rebuild Reason                                    
==========================================================================================================
MinimizeGlobalDataAccess  Code generated and compiled.  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 12.267s

查看生成的代码而不进行优化。这是 MinimizeGlobalDataAccess.c 的一部分。

cfile = fullfile(pwd,'MinimizeGlobalDataAccess_ert_rtw',...
    'MinimizeGlobalDataAccess.c');
coder.example.extractLines(cfile,'/* Model step','/* Model initialize',1, 0);
/* Model step function */
void MinimizeGlobalDataAccess_step(void)
{
  /* MultiPortSwitch: '<Root>/Multiport Switch' incorporates:
   *  Inport: '<Root>/In1'
   */
  switch ((int32_T)rtU.In1) {
   case 1:
    /* Outport: '<Root>/Out1' incorporates:
     *  Constant: '<Root>/Constant'
     */
    rtY.Out1 = 1.0;
    break;

   case 2:
    /* Outport: '<Root>/Out1' incorporates:
     *  Constant: '<Root>/Constant1'
     */
    rtY.Out1 = 2.0;
    break;

   case 3:
    /* Outport: '<Root>/Out1' incorporates:
     *  Constant: '<Root>/Constant2'
     */
    rtY.Out1 = 3.0;
    break;

   default:
    /* Outport: '<Root>/Out1' incorporates:
     *  Constant: '<Root>/Constant3'
     */
    rtY.Out1 = 4.0;
    break;
  }

  /* End of MultiPortSwitch: '<Root>/Multiport Switch' */
}

在静态代码度量报告中,检查 Global Variables 部分。

  1. 在“代码生成报告”窗口中,选择静态代码度量报告

  2. 向下滚动到 Global Variables 部分。

  3. 选择每个变量前的 [+] 符号以展开它。

对全局变量的读写总次数为 5。

启用优化和生成代码

在“配置参数”对话框中,对于优化全局数据访问参数,选择 Minimize global data access 或在 MATLAB 命令行窗口中输入以下命令:

set_param('MinimizeGlobalDataAccess',...
    'GlobalVariableUsage','Minimize global data access');

编译模型。

slbuild(model);
### Starting build procedure for: MinimizeGlobalDataAccess
### Successful completion of build procedure for: MinimizeGlobalDataAccess

Build Summary

Top model targets built:

Model                     Action                        Rebuild Reason                   
=========================================================================================
MinimizeGlobalDataAccess  Code generated and compiled.  Generated code was out of date.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 11.708s

查看优化后的生成代码。这是 MinimizeGlobalDataAccess.c 的一部分。

cfile = fullfile(pwd,'MinimizeGlobalDataAccess_ert_rtw',...
    'MinimizeGlobalDataAccess.c');
coder.example.extractLines(cfile,'/* Model step','/* Model initialize',1, 0);
/* Model step function */
void MinimizeGlobalDataAccess_step(void)
{
  real_T tmp_Out1;

  /* MultiPortSwitch: '<Root>/Multiport Switch' incorporates:
   *  Inport: '<Root>/In1'
   */
  switch ((int32_T)rtU.In1) {
   case 1:
    /* Outport: '<Root>/Out1' incorporates:
     *  Constant: '<Root>/Constant'
     */
    tmp_Out1 = 1.0;
    break;

   case 2:
    /* Outport: '<Root>/Out1' incorporates:
     *  Constant: '<Root>/Constant1'
     */
    tmp_Out1 = 2.0;
    break;

   case 3:
    /* Outport: '<Root>/Out1' incorporates:
     *  Constant: '<Root>/Constant2'
     */
    tmp_Out1 = 3.0;
    break;

   default:
    /* Outport: '<Root>/Out1' incorporates:
     *  Constant: '<Root>/Constant3'
     */
    tmp_Out1 = 4.0;
    break;
  }

  /* End of MultiPortSwitch: '<Root>/Multiport Switch' */

  /* Outport: '<Root>/Out1' */
  rtY.Out1 = tmp_Out1;
}

MinimizeGlobalDataAccess.c 中,代码在每个 case 语句中为局部变量 tmp_Out1 赋予一个常量值。代码中的最后一条语句将 tmp_Out1 的值复制到全局变量 rtY.Out1 中。更少的全局变量引用会使用更少的指令,并提高执行速度。

静态代码度量报告中,检查 Global Variables 部分。由于最大限度地减少了全局数据访问,全局变量的读写总次数从 5 减少到 2。

关闭代码生成报告。

另请参阅

相关主题