Convert Data Copies to Pointer Assignments
The code generator optimizes generated code for vector signal assignments by trying to replace for
loop controlled element assignments and memcpy
function calls with pointer assignments. Pointer assignments avoid expensive data copies. Therefore, they use less stack space and offer faster execution speed than for
loop controlled element assignments and memcpy
function calls. If you assign large data sets to vector signals, this optimization can result in significant improvements to code efficiency.
Configure Model to Optimize Generated Code for Vector Signal Assignments
To apply this optimization:
Verify that your target supports the
memcpy
function.Determine whether your model uses vector signal assignments (such as
Y=expression
) to move large amounts of data. For example, your model could use a Selector block to select input elements from a vector, matrix, or multidimension signal.On the Optimization pane, the Use memcpy for vector assignment parameter, which is on by default, enables the associated Memcpy threshold (bytes) parameter.
Examine the setting of Memcpy threshold (bytes). By default, it specifies 64 bytes as the minimum array size for which
memcpy
function calls or pointer assignments can replacefor
loops in the generated code. Based on the array sizes in your application's vector signal assignments, and target environment considerations on the threshold selection, accept the default value or specify another array size.
Example Model
Open the example model rtwdemo_pointer_conversion
. This model uses a Switch block to assign data to a vector signal. This signal then feeds into a Bus Selector block.
model='rtwdemo_pointer_conversion';
open_system(model);
Generate Code Without Optimization
In the Configuration Parameters dialog box, clear the Use memcpy for vector assignment parameter. Alternatively, use the command-line.
set_param(model, 'EnableMemcpy','off');
Press Ctrl+B to generate code. Alternatively, use the command-line.
slbuild(model);
### Starting build procedure for: rtwdemo_pointer_conversion ### Successful completion of build procedure for: rtwdemo_pointer_conversion Build Summary Top model targets: Model Build Reason Status Build Duration ============================================================================================================================= rtwdemo_pointer_conversion Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 15.023s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 16.012s
View the generated code without the optimization. Here is a portion of rtwdemo_pointer_conversion.c
.
cfile = fullfile('rtwdemo_pointer_conversion_ert_rtw','rtwdemo_pointer_conversion.c'); coder.example.extractLines(cfile,'/* Model step','/* Model initialize',1, 0);
/* Model step function */ void rtwdemo_pointer_conversion_step(void) { int32_T i; int16_T rtb_dataX[100]; int16_T rtb_dataY[100]; /* Switch generated from: '<Root>/Switch' incorporates: * Constant: '<Root>/Constant' * Constant: '<Root>/Constant1' * Constant: '<Root>/Constant2' * Constant: '<Root>/Constant3' * Inport: '<Root>/In1' */ for (i = 0; i < 100; i++) { if (rtU.In1) { rtb_dataX[i] = rtCP_Constant_Value[i]; rtb_dataY[i] = rtCP_Constant1_Value[i]; } else { rtb_dataX[i] = rtCP_Constant2_Value[i]; rtb_dataY[i] = rtCP_Constant3_Value[i]; } } /* End of Switch generated from: '<Root>/Switch' */ /* S-Function (sfix_look1_dyn): '<Root>/Lookup Table Dynamic' incorporates: * Inport: '<Root>/In2' * Outport: '<Root>/Out1' */ /* Dynamic Look-Up Table Block: '<Root>/Lookup Table Dynamic' * Input0 Data Type: Integer S16 * Input1 Data Type: Integer S16 * Input2 Data Type: Integer S16 * Output0 Data Type: Integer S16 * Lookup Method: Linear_Endpoint * */ LookUp_S16_S16( &(rtY.Out1), &rtb_dataY[0], rtU.In2, &rtb_dataX[0], 99U); }
Without the optimization, the generated code contains for
loop controlled element assignments.
Enable Optimization and Generate Code
In the Configuration Parameter dialog box, select the Use memcpy for vector assignment parameter.
set_param(model, 'EnableMemcpy','on')
Generate code.
slbuild(model);
### Starting build procedure for: rtwdemo_pointer_conversion ### Successful completion of build procedure for: rtwdemo_pointer_conversion Build Summary Top model targets: Model Build Reason Status Build Duration ========================================================================================================= rtwdemo_pointer_conversion Generated code was out of date. Code generated and compiled. 0h 0m 12.469s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 13.49s
View the generated code with the optimization. Here is a portion of rtwdemo_pointer_conversion.c
.
cfile = fullfile('rtwdemo_pointer_conversion_ert_rtw','rtwdemo_pointer_conversion.c'); coder.example.extractLines(cfile,'/* Model step','/* Model initialize',1, 0);
/* Model step function */ void rtwdemo_pointer_conversion_step(void) { const int16_T *rtb_dataX_0; const int16_T *rtb_dataY_0; /* Inport: '<Root>/In1' */ if (rtU.In1) { /* Switch generated from: '<Root>/Switch' incorporates: * Constant: '<Root>/Constant' */ rtb_dataX_0 = &rtCP_Constant_Value[0]; /* Switch generated from: '<Root>/Switch' incorporates: * Constant: '<Root>/Constant1' */ rtb_dataY_0 = &rtCP_Constant1_Value[0]; } else { /* Switch generated from: '<Root>/Switch' incorporates: * Constant: '<Root>/Constant2' */ rtb_dataX_0 = &rtCP_Constant2_Value[0]; /* Switch generated from: '<Root>/Switch' incorporates: * Constant: '<Root>/Constant3' */ rtb_dataY_0 = &rtCP_Constant3_Value[0]; } /* End of Inport: '<Root>/In1' */ /* S-Function (sfix_look1_dyn): '<Root>/Lookup Table Dynamic' incorporates: * Inport: '<Root>/In2' * Outport: '<Root>/Out1' */ /* Dynamic Look-Up Table Block: '<Root>/Lookup Table Dynamic' * Input0 Data Type: Integer S16 * Input1 Data Type: Integer S16 * Input2 Data Type: Integer S16 * Output0 Data Type: Integer S16 * Lookup Method: Linear_Endpoint * */ LookUp_S16_S16( &(rtY.Out1), &rtb_dataY_0[0], rtU.In2, &rtb_dataX_0[0], 99U); }
Because the setting of the Memcpy threshold (bytes) parameter is below the array sizes in the generated code, the optimized code contains pointer assignments for the vector signal assignments.
bdclose(model)
See Also
Use memcpy for vector assignment | Memcpy threshold (bytes)