1


txt ファイルにいくつかの情報をたくさんの行に書き込む必要があります。結果は次のようなファイルです。

result.txt:
RED;12;7;0;2;1;4;7;0.0140
RED;12;7;0;2;2;9;7;0.1484
RED;12;7;0;2;3;7;4;0.1787
RED;12;7;0;2;4;2;6;0.7891
RED;12;7;0;2;5;9;6;0.1160
RED;12;7;0;2;6;9;1;0.9893
...

これは、以下のコードによって構築されます(いくつかの縮小された次元があります):

/* the variables 'str1', 'num1', 'day', 'vect1', 'vect2' and 'MD' are inputs of this function
/* str1 is a string 1x1
/* num1 is a integer 1x1 
/* day is a vector 10x1
/* vect1 is a vector 7x1
/* vect2 is a vector 180x1
/* MD is a 4D matrix (7x180x10x15)*/

fid = fopen(path_result, 'Wt');    
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

ここ(stackoverflow の投稿) でいくつかのベクトル化を見ましたが、ここに適用することはできないと思います。何か案は?
前もって感謝します

4

3 に答える 3

3

あらゆる状況に適用できる最初の最適化は、フォーマット文字列を生成することです。それを呼び出しましょうfmt:

fmt       = sprintf('%s;%d;%%d;%d;%d;%%d;%%d;%%d;%%.4f \\n',str1,num1,0,2)
fmt =
RED;4;%d;0;2;%d;%d;%d;%.4f \n

その後、ループ内のコードは次のようになります。

x = sprintf(fmt, i1, day(i2,1), vect1(i3), vect2(i4), MD(i3,i4,i2,i1));

現在、完全にベクトル化されたソリューションは、RAM をトレードオフしますが、9.61 秒から 0.89 秒までの 10.8 倍のスピードアップを実現します。

tic
[a,b,c,d] = ndgrid(vect2,vect1,day,1:15);
out       = sprintf(fmt, [d(:), c(:), b(:), a(:), reshape(permute(MD,[2,1,3,4]),[],1)]'); 
toc
于 2013-08-27T22:50:58.590 に答える
2

コードを最適化するためにできることの 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
于 2013-08-27T19:15:13.323 に答える
0

実際、最初にすべてを作成し、後で記述するだけ (私が試した方法) では速度が向上しないようです。私の最初の考えは、データを保存することでしたsave(file,data,'-ascii')が、予期しない結果になりました。

数値データしかない場合は、おそらく使用できますdlmwriteが、それは現在のオプションではないと思います。

元のコードと比較した私の試みのタイミングを次に示します。これには、いくつかの想定される入力が含まれます。

str1 = 'RED';
num1 = 4;
day = rand(10);
vect1 = 1:7;
vect2 = 1:180;
MD = rand(7,180,10,15);
y=[];

tic
for i1 = 1:15   
    for i2 = 1:10    
        for i3 = 1:7           
           for i4= 1:180

                x=sprintf('%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));
                y{end+1} = x;
            end
        end
    end
end

fid = fopen('test.txt','w');
for i=1:length(y)
         fprintf(fid,y{i});
end
fclose(fid)
t1=toc;

tic
fid = fopen('test.txt', 'Wt');    
for i1 = 1:15   
    for i2 = 1:10    
        for i3 = 1:7           
           for i4= 1:180
                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
t2=toc;

myTime = t1 % 56 secs
originalTime = t2 % 12 secs
于 2013-08-27T14:02:31.283 に答える