MATLAB Answers

Greg
0

MATLAB Function Blocks with Large Data Structures

Asked by Greg
on 8 Aug 2013
I'm building a Simulink model using MATLAB Function Blocks to run some fairly large, complicated functions (the biggest are ~500-700 lines). These functions also take in large data tables to do table lookups and that kind of thing during execution. Those data tables are stored in a single structure within MATLAB and are taken into the MATLAB Function Block via a "Parameter" input.
When I build the model with "Enable Debugging/Animation" turned on in the "MATLAB and Stateflow" configuration parameters, the model runs about 5x slower than without that setting checked. I guess I'm not terribly surprised at that, debugging can have a lot of overhead. Even the faster version seems to be running slower than it should. After I started digging, I realized that what the C-code generated from my M-code looks like when I disable that setting is highly disturbing.
In either case, my large data table are all statically declared in the C-code. Every single data value in my data tables is typed into the C-code in ASCII, making the files 80,000-100,000 lines long sometimes. This isn't totally bad, though, because that data will only be read in as ASCII at compile time and the compiled executable will have all the data as binary in static memory locations.
What is disturbing is that when I disable debugging, all of those data values that are declared statically are copied on every iteration of the sim. The C code looks something like this:
static real_T S_a[4] = {1, 2, 3, 4}
static real_T S_b[6] = {1, 2, 3, 4, 5, 6}
for(i=0;i<4;i++){
S.a[i] = S_a[i];
}
for(i=0;i<6;i++){
S.b[i] = S_b[i];
}
I can't really measure the performance hit of these copies because the only way I've found to get the codegen to not include them is by enabling debugging, but that puts so much other stuff in the code that slows it down. Copying 2 MB of data every single step in Simulink can't be helping the performance of the model, though...
I've tried reproducing this issue with simpler (and non-proprietary) code, but can't seem to make the same issue occur.

  7 Comments

Hi Greg,
Is the non-tunable struct being used as both an input and output in your sub-function calls?
% Sub-function call-site in entry-point
[S,...] = mySubFunction(S,...)
Playing around with some block code, I saw a similar pattern as you initially described when using this pattern for sub-functions where "S" is a non-tunable parameter. When I instead passed the non-tunable struct as an input argument only, the data copy did not happen.
Also, placing "coder.inline('never')" in the sub-function definition may help in figuring out a repro case.
Ketan,
The non-tunable struct is being used as an input only, not an output.
The "coder.inline('never')" helps force the codegen to at least generate a subfunction, but it's still trying to out-think me and preventing me from replicating the issue. The problem now is that in the C code, the structure is never created as a structure and its fields are simply passed into the subfunction as a series of vectors. Is there any way to force the coder to actually use structures in the C code? I tried monkeying around with coder.cstructtype for a bit to see if I could use that to force the structure to exist in the subfunction, but it just generates errors like "This variable already has a type 'sWOEDNasdonw'".
Hi Greg,
The intention of coder.cstructname is to control the name of the struct typedef associated with a struct instance in generated code. I am not aware of any mechanism to direct code generation to implement the passing of the non-tunable struct to a sub-function as passing the entire struct by pointer instead of broken out fields.
Perhaps the non-static variables are needed to implement your MATLAB code in C. If you are interested in investigating this, you could look for assignments to the non-static variables in the generated code.
Other than this, the only other experiment I can think of is to try rewriting some of your struct usages without any intermediary variables. I am not sure if this will influence things, but it may be worth trying if it is not too difficult to implement. So instead of
sub_S = S.sub;
val = sub_S.a(5,2);
write
val = S.sub.a(5,2);

Sign in to comment.

0 Answers