Main Content

将数据副本转换为指针赋值

代码生成器通过尝试用指针赋值取代 for 循环控制的元素赋值和 memcpy 函数调用,来优化向量信号赋值的生成代码。指针赋值可避免代价高昂的数据副本。因此,与 for 循环控制的元素赋值和 memcpy 函数调用相比,指针赋值使用的堆栈空间更少,执行速度更快。当为向量信号赋大型数据集时,这种优化可显著提高代码效率。

配置模型以优化向量信号赋值的生成代码

要应用此优化,请执行下列操作:

  1. 确认您的目标支持 memcpy 函数。

  2. 确定您的模型是否使用向量信号赋值(例如 Y=expression)来移动大量数据。例如,您的模型可能使用 Selector 模块从向量、矩阵或多维信号中选择输入元素。

  3. 优化窗格中,使用 memcpy 进行向量赋值(默认开启)会启用关联的 Memcpy 阈值(字节) 参数。

  4. 检查 Memcpy 阈值(字节) 的设置。默认情况下,它指定 64 字节作为最小数组大小,只有大于或等于此值时,memcpy 函数调用或指针赋值才可取代生成代码中的 for 循环。根据您的应用程序向量信号赋值中的数组大小以及目标环境中关于阈值选择的注意事项,接受默认值或指定其他数组大小。

示例模型

打开示例模型 rtwdemo_pointer_conversion。此模型使用 Switch 模块将数据赋给向量信号。然后,此信号馈入 Bus Selector 模块。

model='rtwdemo_pointer_conversion';
open_system(model);

生成代码但不进行优化

在“配置参数”对话框中,清除使用 memcpy 进行向量赋值参数。或者,使用命令行。

set_param(model, 'EnableMemcpy','off');

Ctrl+B 生成代码。或者,使用命令行。

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

Build Summary

Top model targets:

Model                       Build Reason                                         Status                        Build Duration
=============================================================================================================================
rtwdemo_pointer_conversion  Information cache folder or artifacts were missing.  Code generated and compiled.  0h 0m 14.285s 

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

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

cfile = fullfile('rtwdemo_pointer_conversion_ert_rtw','rtwdemo_pointer_conversion.c');
coder.example.extractLines(cfile,'/* Model step','/* Model initialize',1, 0);
/* Model step function */
void rtwdemo_pointer_conversion_step(void)
{
  int32_T i;
  int16_T rtb_dataX[100];
  int16_T rtb_dataY[100];

  /* Switch generated from: '<Root>/Switch' incorporates:
   *  Constant: '<Root>/Constant'
   *  Constant: '<Root>/Constant1'
   *  Constant: '<Root>/Constant2'
   *  Constant: '<Root>/Constant3'
   *  Inport: '<Root>/In1'
   */
  for (i = 0; i < 100; i++) {
    if (rtU.In1) {
      rtb_dataX[i] = rtCP_Constant_Value[i];
      rtb_dataY[i] = rtCP_Constant1_Value[i];
    } else {
      rtb_dataX[i] = rtCP_Constant2_Value[i];
      rtb_dataY[i] = rtCP_Constant3_Value[i];
    }
  }

  /* End of Switch generated from: '<Root>/Switch' */

  /* S-Function (sfix_look1_dyn): '<Root>/Lookup Table Dynamic' incorporates:
   *  Inport: '<Root>/In2'
   *  Outport: '<Root>/Out1'
   */
  /* Dynamic Look-Up Table Block: '<Root>/Lookup Table Dynamic'
   * Input0  Data Type:  Integer        S16
   * Input1  Data Type:  Integer        S16
   * Input2  Data Type:  Integer        S16
   * Output0 Data Type:  Integer        S16
   * Lookup Method: Linear_Endpoint
   *
   */
  LookUp_S16_S16( &(rtY.Out1), &rtb_dataY[0], rtU.In2, &rtb_dataX[0], 99U);
}

在没有优化的情况下,生成的代码包含 for 循环控制的元素赋值。

启用优化和生成代码

在“配置参数”对话框中,选择使用 memcpy 进行向量赋值参数。

set_param(model, 'EnableMemcpy','on')

生成代码。

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

Build Summary

Top model targets:

Model                       Build Reason                     Status                        Build Duration
=========================================================================================================
rtwdemo_pointer_conversion  Generated code was out of date.  Code generated and compiled.  0h 0m 11.714s 

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

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

cfile = fullfile('rtwdemo_pointer_conversion_ert_rtw','rtwdemo_pointer_conversion.c');
coder.example.extractLines(cfile,'/* Model step','/* Model initialize',1, 0);
/* Model step function */
void rtwdemo_pointer_conversion_step(void)
{
  const int16_T *rtb_dataX_0;
  const int16_T *rtb_dataY_0;

  /* Inport: '<Root>/In1' */
  if (rtU.In1) {
    /* Switch generated from: '<Root>/Switch' incorporates:
     *  Constant: '<Root>/Constant'
     */
    rtb_dataX_0 = &rtCP_Constant_Value[0];

    /* Switch generated from: '<Root>/Switch' incorporates:
     *  Constant: '<Root>/Constant1'
     */
    rtb_dataY_0 = &rtCP_Constant1_Value[0];
  } else {
    /* Switch generated from: '<Root>/Switch' incorporates:
     *  Constant: '<Root>/Constant2'
     */
    rtb_dataX_0 = &rtCP_Constant2_Value[0];

    /* Switch generated from: '<Root>/Switch' incorporates:
     *  Constant: '<Root>/Constant3'
     */
    rtb_dataY_0 = &rtCP_Constant3_Value[0];
  }

  /* End of Inport: '<Root>/In1' */

  /* S-Function (sfix_look1_dyn): '<Root>/Lookup Table Dynamic' incorporates:
   *  Inport: '<Root>/In2'
   *  Outport: '<Root>/Out1'
   */
  /* Dynamic Look-Up Table Block: '<Root>/Lookup Table Dynamic'
   * Input0  Data Type:  Integer        S16
   * Input1  Data Type:  Integer        S16
   * Input2  Data Type:  Integer        S16
   * Output0 Data Type:  Integer        S16
   * Lookup Method: Linear_Endpoint
   *
   */
  LookUp_S16_S16( &(rtY.Out1), &rtb_dataY_0[0], rtU.In2, &rtb_dataX_0[0], 99U);
}

由于 Memcpy 阈值(字节) 参数的设置低于生成的代码中的数组大小,因此优化后的代码中包含用于向量信号赋值的指针赋值。

bdclose(model)

另请参阅

|

相关主题