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.
slbuild(model)
### Starting build procedure for: rtwdemo_optimizedatastorebuffers ### Successful completion of build procedure for: rtwdemo_optimizedatastorebuffers Build Summary Top model targets: Model Build Reason Status Build Duration =================================================================================================================================== rtwdemo_optimizedatastorebuffers Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 26.687s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 31.823s
View the generated code without the optimization. This code is in rtwdemo_optimizedatastorebuffers.c
.
cfile = fullfile('rtwdemo_optimizedatastorebuffers_ert_rtw',... 'rtwdemo_optimizedatastorebuffers.c'); coder.example.extractLines(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: Model Build Reason Status Build Duration =============================================================================================================== rtwdemo_optimizedatastorebuffers Generated code was out of date. Code generated and compiled. 0h 0m 12.55s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 13.621s
View the generated code with the optimization. This code is in rtwdemo_optimizedatastorebuffers.c
.
cfile = fullfile('rtwdemo_optimizedatastorebuffers_ert_rtw',... 'rtwdemo_optimizedatastorebuffers.c'); coder.example.extractLines(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; } /* FunctionCaller: '<Root>/SimFuncCall' incorporates: * DataStoreWrite: '<Root>/DSW' * Inport: '<Root>/DataNew' * Switch: '<Root>/Switch' */ 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)
See Also
Reuse buffers for Data Store Read and Data Store Write blocks