Prevent loop merging in Matlab coder
2 views (last 30 days)
Show older comments
Matlab tends to merge for loops of the same size as:
xyz = zeros(2048,3);
for i = 1:size(xyz,1)
xyz(i,:)= 123;
end
di=nan(2048,1);
Then the code generated in C++ will be:
for (i=0; i<2048; i++){
for (j=0; j<3; j++){
xyz[i * 3 + j] = 123;
}
di[i] = rtNaN;
}
How can I let coder know that di should be in another for loop to obtain the best speed due to cache misses?
Desired behaviour:
for (i=0; i<2048; i++){
for (j=0; j<3; j++){
xyz[i * 3 + j] = 123;
}
}
for (i=0; i<2048; i++){
di[i] = rtNaN;
}
0 Comments
Answers (1)
Matan Silver
on 25 Apr 2022
Edited: Matan Silver
on 25 Apr 2022
Hi Marc,
One way to achieve this is to factor out the initialization of the "di" variable into a non-inlined helper function. This will make sure it is not pulled into the loop. See below for the comparison:
function [xyz, di] = foo
xyz = zeros(2048,3);
for i = 1:size(xyz,1)
xyz(i,:)= 123;
end
di=nan(2048,1);
end
% void foo(double xyz[6144], double di[2048])
% {
% int i;
% for (i = 0; i < 2048; i++) {
% xyz[i] = 123.0;
% xyz[i + 2048] = 123.0;
% xyz[i + 4096] = 123.0;
% di[i] = rtNaN;
% }
% }
Compared to an example with the helper function:
function [xyz, di] = foo_noninline
xyz = zeros(2048,3);
for i = 1:size(xyz,1)
xyz(i,:)= 123;
end
di=initDI();
end
function di = initDI()
coder.inline('never');
di = nan(2048,1);
end
% static void initDI(double di[2048])
% {
% int i;
% for (i = 0; i < 2048; i++) {
% di[i] = rtNaN;
% }
% }
%
% /*
% * Arguments : double xyz[6144]
% * double di[2048]
% * Return Type : void
% */
% void foo_noninline(double xyz[6144], double di[2048])
% {
% int i;
% for (i = 0; i < 2048; i++) {
% xyz[i] = 123.0;
% xyz[i + 2048] = 123.0;
% xyz[i + 4096] = 123.0;
% }
%
% initDI(di);
% }
Hopefully this helps!
Matan
1 Comment
Matan Silver
on 25 Apr 2022
Side-note, depending on the architecture and environment, you could also get better performance by playing with "coder.rowMajor", which will change the dimension of the loop variables. For example, note how the three unrolled assignments in the loop are much closer to each other in memory now:
function [xyz, di] = foo_noninline
coder.rowMajor;
xyz = zeros(2048,3);
for i = 1:size(xyz,1)
xyz(i,:)= 123;
end
di=initDI();
end
function di = initDI()
coder.inline('never');
di = nan(2048,1);
end
% static void initDI(double di[2048])
% {
% int i;
% for (i = 0; i < 2048; i++) {
% di[i] = rtNaN;
% }
% }
%
% /*
% * Arguments : double xyz[6144]
% * double di[2048]
% * Return Type : void
% */
% void foo_noninline(double xyz[6144], double di[2048])
% {
% int i;
% for (i = 0; i < 2048; i++) {
% xyz[3 * i] = 123.0;
% xyz[3 * i + 1] = 123.0;
% xyz[3 * i + 2] = 123.0;
% }
%
% initDI(di);
% }
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!