Main Content

Data Copy Reduction for Data Store Read and Data Store Write Blocks

This example shows how the code generator removes temporary buffers for Data Store Read and Data Store Write blocks. This optimization improves execution speed and reduces RAM consumption.

Example Model

The model rtwdemo_optimizedatastorebuffers contains the Function caller UpdateFunc, which calls the Simulink Function DefineUpdateFunc. The Data Store Read block DSR reads from mem. The Data Store Write block DSW writes to mem.

model='rtwdemo_optimizedatastorebuffers';
open_system(model);

Generate Code without Optimization

In the Configuration Parameters dialog box, deselect the Reuse buffers for Data Store Read and Data Store Write blocks parameter or at the MATLAB command prompt, enter this command:

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

Build the model.

currentDir = pwd;
[~,cgDir] = rtwdemodir();
slbuild(model)
### Starting build procedure for: rtwdemo_optimizedatastorebuffers
### Successful completion of build procedure for: rtwdemo_optimizedatastorebuffers

Build Summary

Top model targets built:

Model                             Action                       Rebuild Reason                                    
=================================================================================================================
rtwdemo_optimizedatastorebuffers  Code generated and compiled  Code generation information file does not exist.  

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

View the generated code without the optimization. This code is in rtwdemo_optimizedatastorebuffers.c.

cfile = fullfile(cgDir,'rtwdemo_optimizedatastorebuffers_ert_rtw',...
    'rtwdemo_optimizedatastorebuffers.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void step(void)
{
  real_T rtb_DSR_last;
  real_T rtb_SimFuncCall_o1;
  real_T rtb_Sum_p;

  /* DataStoreRead: '<Root>/DSR' */
  rtb_DSR_last = mem.last;

  /* Switch: '<Root>/Switch' incorporates:
   *  Constant: '<Root>/Constant'
   *  DataStoreRead: '<Root>/DSR'
   *  Inport: '<Root>/Clear'
   */
  if (rtU.Clear) {
    rtb_SimFuncCall_o1 = 0.0;
  } else {
    rtb_SimFuncCall_o1 = mem.max;
  }

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

  /* FunctionCaller: '<Root>/SimFuncCall' incorporates:
   *  Inport: '<Root>/DataNew'
   */
  UpdateFunc(rtb_SimFuncCall_o1, rtU.DataNew, &rtb_SimFuncCall_o1, &rtb_Sum_p);

  /* DataStoreWrite: '<Root>/DSW' */
  mem.last = rtb_SimFuncCall_o1;
  mem.max = rtb_Sum_p;

  /* Outport: '<Root>/Delta' incorporates:
   *  DataStoreRead: '<Root>/DSR'
   *  Inport: '<Root>/DataNew'
   *  Sum: '<Root>/Sum'
   */
  rtY.Delta = rtU.DataNew - rtb_DSR_last;
}

The generated code contains data copies for the Data Store Read and Data Store Write blocks, respectively.

Generate Code with Optimization

In the Configuration Parameters dialog box, clear the Reuse buffers for Data Store Read and Data Store Write blocks parameter or at the MATLAB command prompt, enter this command:

set_param(model,'OptimizeDataStoreBuffers','on');

Build the model.

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

Build Summary

Top model targets built:

Model                             Action                       Rebuild Reason                   
================================================================================================
rtwdemo_optimizedatastorebuffers  Code generated and compiled  Generated code was out of date.  

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

View the generated code with the optimization. This code is in rtwdemo_optimizedatastorebuffers.c.

cfile = fullfile(cgDir,'rtwdemo_optimizedatastorebuffers_ert_rtw',...
    'rtwdemo_optimizedatastorebuffers.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void step(void)
{
  real_T rtb_DSR_last;
  real_T tmp;

  /* DataStoreRead: '<Root>/DSR' */
  rtb_DSR_last = mem.last;

  /* Switch: '<Root>/Switch' incorporates:
   *  Constant: '<Root>/Constant'
   *  DataStoreRead: '<Root>/DSR'
   *  Inport: '<Root>/Clear'
   */
  if (rtU.Clear) {
    tmp = 0.0;
  } else {
    tmp = mem.max;
  }

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

  /* FunctionCaller: '<Root>/SimFuncCall' incorporates:
   *  DataStoreWrite: '<Root>/DSW'
   *  Inport: '<Root>/DataNew'
   */
  UpdateFunc(tmp, rtU.DataNew, &mem.last, &mem.max);

  /* Outport: '<Root>/Delta' incorporates:
   *  DataStoreRead: '<Root>/DSR'
   *  Inport: '<Root>/DataNew'
   *  Sum: '<Root>/Sum'
   */
  rtY.Delta = rtU.DataNew - rtb_DSR_last;
}

The data copy for the Data Store Write block is not in the generated code. The code contains the data copy for the Data Store Read block because the Sum block executes after the Data Store Write block. The generated code contains the variable rtb_DSR_last to hold the output of the Sum block. Therefore, the Sum block gets the values that SimFuncCall calculates at the start of the time step rather than those values at the next time step. If the priority of the Sum block is lower than SimFuncCall, the code generator can remove the data copy for the Data Store Read block. Some other cases in which the code generator might not eliminate data copies are:

  • A Simulink Function internally writes to the Data Store Memory block.

  • The Data Store Read or Data Store Write blocks select elements of an array from the Data Store Memory block.

  • The Data Store Memory block has a custom storage class.

  • The Data Store Read and Data Store Write blocks occur on the same block unless that block is a Bus Assignment block or an Assignment block.

Close the model and clean up.

bdclose(model)
rtwdemoclean;
cd(currentDir)

See Also

Related Topics