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.
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);
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(); rtwbuild(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 10.4s
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.
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.
rtwbuild(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 9.468s
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)
Reuse buffers for Data Store Read and Data Store Write blocks