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
Open the Configuration Parameters dialog box.
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
Pass reusable subsystem outputs as