Optimize Generated Code by Using Signal Labels to Guide Buffer Reuse
If your model has the optimal parameter settings for removing data copies, you might be able to remove additional data copies by using signal labels. After studying the generated code and the Static Code Metrics Report and identifying areas where you think buffer reuse is possible, you can add labels to signal lines. If possible, the code generator reorders block operations to implement the reuse specification.
Specifying buffer reuse improves execution speed and may reduce RAM consumption.
Example Model
The model SignalLabelReuse
demonstrates how you can use signal labels to request buffer reuse for block input and output signals. The generated code can use the same variable for the Saturation and Atomic Subsystem block outputs because those signals contain the same label and the Use Signal Labels to Guide Buffer Reuse parameter is selected.
model='SignalLabelReuse';
open_system(model);
Generate Code Without Optimization
The Use Signal Labels to Guide Buffer Reuse parameter is on by default. Open the Configuration Parameters dialog box and clear the parameter. Alternatively, use the command-line.
set_param(model, 'LabelGuidedReuse', 'off');
Build the model.
slbuild(model)
### Starting build procedure for: SignalLabelReuse ### Successful completion of build procedure for: SignalLabelReuse Build Summary Top model targets: Model Build Reason Status Build Duration =================================================================================================================== SignalLabelReuse Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 12.671s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 13.969s
View the generated SignalLabelReuse_step
function.
file = fullfile('SignalLabelReuse_ert_rtw','SignalLabelReuse.c'); coder.example.extractLines(file,'/* Model step function */','/* Model initialize function',1,1);
/* Model step function */ void SignalLabelReuse_step(void) { real_T rtb_Bias[4]; real_T rtb_Saturation[4]; real_T rtb_Bias_0; int32_T i; AtomicSubsystem(rtU.In1, rtb_Bias); for (i = 0; i < 4; i++) { rtb_Bias_0 = rtb_Bias[i]; if (rtb_Bias_0 > 10.0) { rtb_Saturation[i] = 10.0; } else if (rtb_Bias_0 < -10.0) { rtb_Saturation[i] = -10.0; } else { rtb_Saturation[i] = rtb_Bias_0; } rtb_Bias[i] = 3.0 * rtb_Bias_0; } AtomicSubsystem1(rtb_Saturation, rtb_Bias, rtY.Out1); }
By default, within the for loop, the Gain block executes after the Saturation block. The generated code contains two local variables rtb_Saturation
and rtb_Bias
for holding intermediate results.
Generate Code with Optimization
Open the Configuration Parameters dialog box. Select the Use Signal Labels to Guide Buffer Reuse parameter. Alternatively, use the command-line.
set_param(model, 'LabelGuidedReuse', 'on');
Build the model.
slbuild(model)
### Starting build procedure for: SignalLabelReuse ### Successful completion of build procedure for: SignalLabelReuse Build Summary Top model targets: Model Build Reason Status Build Duration =============================================================================================== SignalLabelReuse Generated code was out of date. Code generated and compiled. 0h 0m 9.7745s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 10.585s
View the generated SignalLabelReuse_step
function.
file = fullfile('SignalLabelReuse_ert_rtw','SignalLabelReuse.c'); coder.example.extractLines(file,'/* Model step function */','/* Model initialize function',1,1)
/* Model step function */ void SignalLabelReuse_step(void) { real_T rtb_Gain1[4]; real_T Out1; int32_T i; AtomicSubsystem(rtU.In1, rtY.Out1); for (i = 0; i < 4; i++) { Out1 = rtY.Out1[i]; rtb_Gain1[i] = 3.0 * Out1; if (Out1 > 10.0) { rtY.Out1[i] = 10.0; } else if (Out1 < -10.0) { rtY.Out1[i] = -10.0; } } AtomicSubsystem1(rtY.Out1, rtb_Gain1, rtY.Out1); }
The code generator changed the block execution order so that within the for
loop, the Saturation block executes after the Gain block. The generated code contains one local variable rtb_Gain1
for holding intermediate results.
In addition to requesting which buffers to reuse, another possible use case is to request buffer reuse for block input and output signals that are complex.
Using Label-Based Reuse Versus Reusable Storage Classes
You can also use the same Reusable
storage class specification on different signal lines to specify which buffers to reuse. As compared to using Reusable
storage classes, using signal labels to specify reuse has these benefits:
Signal labels are not observation points in the generated code, so using them does not block other optimizations such as dead code elimination and expression folding.
The code generator does not force a signal with a label to be a global variable in the generated code. The signal can be a local or global variable.
Signals with labels can reuse buffers with signals that do not have labels, so reuse among local and global variables is possible.
Using signal labels is a more conservative method of specifying reuse than using Reusable
storage classes. The code generator does not implement label-based reuse when it can implement reuse by using Reusable
storage classes in these cases:
Reuse that can potentially prevent other optimizations from occurring in the generated code.
Reuse on root inport and outport ports.
Reuse across model reference or subsystem boundaries.
Within a subsystem, buffer reuse on an intermediary signal and an input or output port.
See Also
Use signal labels to guide buffer reuse