0

ベクトル化に取り組んでいるforループが1つあります。問題は、ベクトル化されると、コードが3倍遅くなることです。熱力学的アルゴリズムの一部である元のコードは次のとおりです。

Matrix=rand(10,10,20);
someMatrix=rand(50);
m=5; n=6; CONSTj=9; CONSTk=10; maxGrid=5;
Total=0;

for var=0:maxGrid
    Factor=1;
    p=CONSTj-var;
    q=CONSTk-var;

    if p>=1 && q>=1
        Factor=Matrix(n,m,p)*Matrix(m,n,q);
    elseif p>=1 && q<1
        Factor=Matrix(n,m,p);
    elseif p<1 && q>=1
        Factor=Matrix(m,n,q);
    end

    Total=Total+Factor*(someMatrix(m)^var);
end

私はそれを次のようにベクトル化しました:

Matrix=rand(10,10,20);
someMatrix=rand(50);
m=5; n=6; CONSTj=9; CONSTk=10; maxGrid=5;

var=(0:maxGrid)';
Factor=ones(maxGrid+1,1);
tempoJ=zeros(maxGrid+1,1);
tempoK=zeros(maxGrid+1,1);
p=CONSTj-var;
q=CONSTk-var;

index1 = find(p>=1 & q>=1);
index2 = find(p>=1 & q<1 );
index3 = find(p<1  & q>=1);

tempoJ(index1)=squeeze(Matrix(n,m,p(index1)));
tempoJ(index2)=squeeze(Matrix(n,m,p(index2)));
tempoK(index1)=squeeze(Matrix(m,n,q(index1)));
tempoK(index3)=squeeze(Matrix(m,n,q(index3)));

Factor(index1)=tempoJ(index1).*tempoK(index1);
Factor(index2)=tempoJ(index2);
Factor(index3)=tempoK(index3);

Total=Factor.*(someMatrix(m).^var);
Total=sum(Total);

プロファイラーによると、findsqueezesumは最も時間を消費する関数です。ifステートメントから情報を取得するために何かできると思いますが、インデックスを変更せずに簡単な方法を見つけることはできません。

4

2 に答える 2

0

わかりました、これは答えではありませんが、コメントにはすべてを入力するのに十分なスペースがありません。

これが私が使用したテストコードです。OPが提供したものに基づいています。maxGridとにいくつかの負の値があるように、を15に上げたことに注意してpくださいq。他の行列のサイズも大きくしました。findsqueeze関数呼び出しも削除しました。

結果の出力は次のとおりです。

Elapsed time is 0.078117 seconds.
Elapsed time is 0.096412 seconds.

最終的に、これはコードの最初のレンディションがより高速に実行されていることを示しています。

tic
Matrix=rand(100,100,200); 
someMatrix=rand(500); 
m=5; n=6; CONSTj=9; CONSTk=10; maxGrid=15; 
Total=0; 

for var=0:maxGrid 
    Factor=1; 
    p=CONSTj-var; 
    q=CONSTk-var; 

    if p>=1 && q>=1 
        Factor=Matrix(n,m,p)*Matrix(m,n,q); 
    elseif p>=1 && q<1 
        Factor=Matrix(n,m,p); 
    elseif p<1 && q>=1 
        Factor=Matrix(m,n,q); 
    end 

    Total=Total+Factor*(someMatrix(m)^var); 
end 
toc

tic
Matrix=rand(100,100,200); 
someMatrix=rand(500); 
m=5; n=6; CONSTj=9; CONSTk=10; maxGrid=15; 

var=(0:maxGrid)'; 
Factor=ones(maxGrid+1,1); 
tempoJ=zeros(maxGrid+1,1); 
tempoK=zeros(maxGrid+1,1); 
p=CONSTj-var; 
q=CONSTk-var; 

% index1 = find(p>=1 & q>=1); 
index1 = ((p>=1) & (q>=1));
% index2 = find(p>=1 & q<1 ); 
index2 = ((p>=1)&(q<1));
% index3 = find(p<1  & q>=1); 
index3 = ((p<1)&(q>=1));

tempoJ(index1)=(Matrix(n,m,p(index1))); 
tempoJ(index2)=(Matrix(n,m,p(index2))); 
tempoK(index1)=(Matrix(m,n,q(index1))); 
tempoK(index3)=(Matrix(m,n,q(index3))); 

Factor(index1)=tempoJ(index1).*tempoK(index1); 
Factor(index2)=tempoJ(index2); 
Factor(index3)=tempoK(index3); 

Total=Factor.*(someMatrix(m).^var); 
Total=sum(Total); 
toc
于 2012-07-24T18:39:04.850 に答える
0

私は実際にはこのコードをベクトル化しません。Matlabの最近のバージョンには優れたJITコンパイラがあり、コードのベクトル化では、以前のバージョンと同じパフォーマンスの向上はありません。

元のコードは、理解と保守がはるかに簡単です。どうしてもパフォーマンスが必要な場合は、このためのMEX関数(C)を作成することを検討します。

ただし、コードをベクトル化することに設定されている場合は、不要な呼び出しを排除しfindますsqueeze(@mutzmatronが提案しているように)。交換:

index1 = find(p>=1 & q>=1);
index2 = find(p>=1 & q<1 );
index3 = find(p<1  & q>=1);

tempoJ(index1)=squeeze(Matrix(n,m,p(index1)));
tempoJ(index2)=squeeze(Matrix(n,m,p(index2)));
tempoK(index1)=squeeze(Matrix(m,n,q(index1)));
tempoK(index3)=squeeze(Matrix(m,n,q(index3)));

と:

p_gt1 = p >= 1;
q_gt1 = q >= 1;

index1 =  p_gt1 &  q_gt1;
index2 =  p_gt1 & ~q_gt1;
index3 = ~p_gt1 &  q_gt1;

tempoJ(index1)=Matrix(n,m,p(index1));
tempoJ(index2)=Matrix(n,m,p(index2));
tempoK(index1)=Matrix(m,n,q(index1));
tempoK(index3)=Matrix(m,n,q(index3));

する必要はありませんsqueeze。の行のRHSはsqueezeLHSと同じ数の要素を持っているため、Matlabはそれらを1対1でマップし、これを埋めます。

この改善があっても、ベクトル化されたコードは元のforループよりも少し遅くなります。私はそれぞれを使用して時間を計りましたTIMEIT

% 'foo'     your original for loop
% 'foo_v0'  the original vector code, with find and squeeze
% 'foo_v'   the modified vector code, without find/squeeze

>> timeit(@()foo(Matrix,someMatrix))
ans =
   1.1482e-05

>> timeit(@()foo_v(Matrix,someMatrix))
ans =
   2.8039e-05

>> timeit(@()foo_v0(Matrix,someMatrix))
ans =
   1.3256e-04

確かに、これは問題を説明するために簡略化したコードです。実際の問題で異なる結果が得られる場合があります。ただし、Matlabはコードのコンパイルに関してよりスマートになっているため、ベクトル化によって以前の速度の向上は得られないことに注意してください。

于 2012-07-24T18:40:25.400 に答える