コードを最適化するためにできることの 1 つは、コードの「繰り返される」ビットを探すことです。あなたの場合、最も内側のループですべての結果文字列をフォーマットしますが、文字列の多くは変更されません。また、区切り文字列を数回「フォーマット」します';'
-フォーマット文字列に直接含めることができます(フォーマット文字列にテキストとフォーマットコマンドを散在させることができます)。これらのアイデアをいくつかの異なる方法で組み合わせ、タイミングを合わせました。
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);
私のマシンでは、これにより次のベンチマークが得られました。
Original loop: 15.9 sec
Faster format: 9.2 sec
With sprintf: 8.2 sec
preformat: 6.2 sec
「事前フォーマット」は可能な限り効率的に行われませんでした - それは説明のためだけにありました。中間文字列x
は、計算される頻度がはるかに低くなり、再利用されます。
最後に、コードの「ベクトル化」バージョンを作成しました。これは、全体sprintf
が 1 行で行われることを意味します。これには、適切な要素を含む大きなセル配列 ( Kahuna
、以下) を作成する必要があります。実際には、上記の最後のコード (「事前フォーマット」を使用) よりもわずかに効率が悪いことがわかりますが、念のために以下に示します。
%% 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