Main Content

Optimize Generated Code by Passing Reusable Subsystem Outputs as Individual Arguments

This example shows how passing reusable subsystem outputs as individual arguments instead of as a pointer to a structure stored in global memory optimizes the generated code. This optimization conserves RAM consumption and increases code execution speed by reducing global memory usage and eliminating data copies from local variables back to global block I/O structures.

Example Model

Consider the model rtwdemo_reusable_sys_outputs. In this model, the reusable subsystem outputs feed the root outputs of the model.

model = 'rtwdemo_reusable_sys_outputs';
open_system(model);

Generate Code Without This Optimization

Generate code for this model while passing subsystem outputs as a structure reference.

Build the model.

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

Build Summary

Top model targets:

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

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

The code snippet shows portions of rtwdemo_reusable_sys_outputs.c. Notice the global block I/O structure and in the model step function a data copy from this structure.

cfile = fullfile('rtwdemo_reusable_sys_outputs_ert_rtw',...
'rtwdemo_reusable_sys_outputs.c');
coder.example.extractLines(cfile, '/* Output and update for atomic system',...
'/* Model initialize', 1, 0);
/* Output and update for atomic system: '<Root>/ReusableSubsystem' */
static void ReusableSubsystem(real_T rtu_In1, real_T rtu_In2, real_T rtu_In3,
  DW_ReusableSubsystem *localDW)
{
  /* Gain: '<S1>/Gain' */
  localDW->Gain = 5.0 * rtu_In1;

  /* Gain: '<S1>/Gain1' */
  localDW->Gain1 = 6.0 * rtu_In2;

  /* Gain: '<S1>/Gain2' */
  localDW->Gain2 = 7.0 * rtu_In3;
}

/* Model step function */
void rtwdemo_reusable_sys_outputs_step(void)
{
  /* Outputs for Atomic SubSystem: '<Root>/ReusableSubsystem' */

  /* Inport: '<Root>/In1' incorporates:
   *  Inport: '<Root>/In2'
   *  Inport: '<Root>/In3'
   */
  ReusableSubsystem(rtU.In1, rtU.In2, rtU.In3, &rtDW.ReusableSubsystem_d);

  /* End of Outputs for SubSystem: '<Root>/ReusableSubsystem' */

  /* Outport: '<Root>/Out1' */
  rtY.Out1 = rtDW.ReusableSubsystem_d.Gain;

  /* Outport: '<Root>/Out2' */
  rtY.Out2 = rtDW.ReusableSubsystem_d.Gain1;

  /* Outport: '<Root>/Out3' */
  rtY.Out3 = rtDW.ReusableSubsystem_d.Gain2;
}

Enable This Optimization

  1. Open the Configuration Parameters dialog box.

  2. On the Optimization pane, set Pass reusable subsystem outputs as to Individual arguments.

Alternatively, you can use the command-line API to enable the optimization:

set_param(model, 'PassReuseOutputArgsAs', 'Individual arguments');

Generate Code with This Optimization

With this optimization, the ReusableSubsystem function has three output arguments, which are direct references to the external outputs. The rtDW global structure no longer exists, and the data copies from this structure to the rtY (external outputs) structure are not in the generated code.

Build the model.

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

Build Summary

Top model targets:

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

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

The code snippet below is a portion of rtwdemo_reusable_sys_outputs.c. Observe the optimized code.

coder.example.extractLines(cfile,'/* Output and update for atomic system',...
'/* Model initialize', 1, 0);
/* Output and update for atomic system: '<Root>/ReusableSubsystem' */
static void ReusableSubsystem(real_T rtu_In1, real_T rtu_In2, real_T rtu_In3,
  real_T *rty_Out1, real_T *rty_Out2, real_T *rty_Out3)
{
  /* Gain: '<S1>/Gain' */
  *rty_Out1 = 5.0 * rtu_In1;

  /* Gain: '<S1>/Gain1' */
  *rty_Out2 = 6.0 * rtu_In2;

  /* Gain: '<S1>/Gain2' */
  *rty_Out3 = 7.0 * rtu_In3;
}

/* Model step function */
void rtwdemo_reusable_sys_outputs_step(void)
{
  /* Outputs for Atomic SubSystem: '<Root>/ReusableSubsystem' */

  /* Inport: '<Root>/In1' incorporates:
   *  Inport: '<Root>/In2'
   *  Inport: '<Root>/In3'
   *  Outport: '<Root>/Out1'
   *  Outport: '<Root>/Out2'
   *  Outport: '<Root>/Out3'
   */
  ReusableSubsystem(rtU.In1, rtU.In2, rtU.In3, &rtY.Out1, &rtY.Out2, &rtY.Out3);

  /* End of Outputs for SubSystem: '<Root>/ReusableSubsystem' */
}

Close the model.

bdclose(model)

See Also

Related Topics