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 rtwdemo_label_guided_reuse demonstrates how you can use signal labels to request buffer reuse for block input and output signals. For this model, the code generator can use the same variable for the Atomic Subsystem and either the Gain or Saturation block outputs. The generated code uses 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.

Generate Code Without Optimization

  1. Open the model.

    model='rtwdemo_label_guided_reuse';
    open_system(model);
  2. In the Configuration Parameters dialog box, clear the Use Signal Labels to Guide Buffer Reuse parameter.

  3. Build the model. The rtwdemo_label_guided_reuse_step function contains this code:

    void rtwdemo_label_guided_reuse_step(void)
    {
      real_T rtb_Saturation[4];
      real_T rtb_Bias[4];
      int32_T i;
      AtomicSubsystem(rtU.In1, rtb_Bias);
      for (i = 0; i < 4; i++) {
        if (rtb_Bias[i] > 10.0) {
          rtb_Saturation[i] = 10.0;
        } else if (rtb_Bias[i] < -10.0) {
          rtb_Saturation[i] = -10.0;
        } else {
          rtb_Saturation[i] = rtb_Bias[i];
        }
    
        rtb_Bias[i] *= 3.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 uses the same variable for the output of the Atomic Subsystem and the Gain blocks. As a result, the generated code contains two local variables rtb_Saturation and rtb_Bias for holding intermediate results.

Generate Code with Optimization

In the Configuration Parameters dialog box, select the Use Signal Labels to Guide Buffer Reuse parameter and build the model. The rtwdemo_label_guided_reuse_step function contains this code:

void rtwdemo_label_guided_reuse_step(void)
{
  real_T rtb_Gain1[4];
  int32_T i;
  AtomicSubsystem(rtU.In1, rtY.Out1);
  for (i = 0; i < 4; i++) {
    rtb_Gain1[i] = 3.0 * rtY.Out1[i];
    if (rtY.Out1[i] > 10.0) {
      rtY.Out1[i] = 10.0;
    } else {
      if (rtY.Out1[i] < -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 Custom Storage Classes

You can also use the same Reusable custom storage class specification on different signal lines to specify which buffers to reuse. As compared to using Reusable custom 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 custom storage classes. The code generator does not implement label-based reuse when it can implement reuse by using Reusable custom 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

Related Topics