One of the things you can do to optimize your code is to look for "repeated" bits of code. In your case, you format ALL of the result string in the innermost loop - although much of the string doesn't change. You also "format" the separator string ';'
several times - you can have that directly in your formatting string (you can intersperse text and formatting commands in the format string). I combined these ideas in a few different ways, and timed them:
str1 = 'hello';
num1 = 123;
day = (1:10)';
vect1 = (1:7)';
vect2 = (1:180)';
MD = rand(7,180,10,15);
path_result = './mixedOutput1.txt';
fid = fopen(path_result, 'Wt');
tic
for i1 = 1:15
for i2 = 1:10
for i3 = 1:7
for i4= 1:180
% /* print all the values */
fprintf(fid,'%s%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%.4f \n',...
str1,';',num1,';',i1,';',0,';',2,';',...
day(i2,1),';',vect1(i3),';',...
vect2(i4),';',MD(i3,i4,i2,i1));
end
end
end
end
fprintf(1, 'time for original loop: %.2f sec\n',toc)
fclose(fid);
%%
path_result = './mixedOutput2.txt';
fid = fopen(path_result, 'Wt');
tic
for i1 = 1:15
for i2 = 1:10
for i3 = 1:7
for i4= 1:180
% /* print all the values */
fprintf(fid,'%s;%d;%d;0;2;%d;%d;%d;%.4f \n',...
str1, num1, i1, day(i2,1), vect1(i3), vect2(i4),MD(i3,i4,i2,i1));
end
end
end
end
fprintf(1, 'time for faster loop: %.2f sec\n',toc)
fclose(fid);
%%
path_result = './mixedOutput3.txt';
fid = fopen(path_result, 'Wt');
tic
y = cell(1,15*10*7*180);
cc = 0;
for i1 = 1:15
for i2 = 1:10
for i3 = 1:7
for i4= 1:180
% /* print all the values */
cc = cc + 1;
y{1,cc} = sprintf('%s;%d;%d;0;2;%d;%d;%d;%.4f \n',...
str1, num1, i1, day(i2,1), vect1(i3), vect2(i4), MD(i3,i4,i2,i1));
end
end
end
end
fprintf(1, 'time for loop with sprintf intermediate step: %.2f sec\n', toc)
fprintf(fid, '%s', y{:});
fprintf(1, 'time including file write: %.2f sec\n', toc);
fclose(fid);
%% optimize loop more:
path_result = './mixedOutput4.txt';
fid = fopen(path_result, 'Wt');
tic
y = cell(1,15*10*7*180);
cc = 0;
for i1 = 1:15
for i2 = 1:10
for i3 = 1:7
x = sprintf('%s;%d;%d;0;2;%d;%d;', ...
str1, num1, i1, day(i2,1), vect1(i3));
for i4= 1:180
fprintf(fid, '%s%d;%.4f \n', ...
x, vect2(i4), MD(i3,i4,i2,i1));
end
end
end
end
fprintf(1, 'time for fastest loop: %.2f sec\n', toc);
fclose(fid);
On my machine, this resulted in the following benchmarks:
Original loop: 15.9 sec
Faster format: 9.2 sec
With sprintf: 8.2 sec
preformat: 6.2 sec
The "preformat" was not done as efficiently as possible - it was just there for illustration. The intermediate string x
is computed much less frequently, then re-used.
Finally - I did create a "vectorized" version of the code - meaning that the entire sprintf
happens in a single line. This requires creating a big cell array (Kahuna
, below) with the right elements - it turns out that's actually marginally less efficient than the last code above (with the "preformatting"), but here it is just in case:
%% truly vectorized:
tic
Kahuna = cell(7, 15*10*7*180);
N = 15 * 10 * 7 * 180;
N1 = ones(1, N);
% final order needs to be [180 7 10 15] - inner loop first
Kahuna(1,:) = cellstr(repmat(str1, [N 1]))';
Kahuna(2,:) = mat2cell(repmat(num1, [N 1]), N1, 1);
Kahuna(3,:) = mat2cell(reshape(repmat(reshape(1:15, 1, 1, 1, 15), [180 7 10 1]), [], 1), N1, 1);
Kahuna(4,:) = mat2cell(reshape(repmat(reshape(day, 1, 1, 10, 1), [180 7 1 15]), [], 1), N1, 1);
Kahuna(5,:) = mat2cell(reshape(repmat(reshape(vect1, 1, 7, 1, 1), [180 1 10 15]), [], 1), N1, 1);
Kahuna(6,:) = mat2cell(reshape(repmat(reshape(vect2, 180, 1, 1, 1), [ 1 7 10 15]), [], 1), N1, 1);
Kahuna(7,:) = mat2cell(reshape(permute(MD, [2 1 3 4]), [], 1), N1, 1);
x = sprintf('%s;%d;%d;0;2;%d;%d;%d;%.4f \n', Kahuna{:});
toc