Main Content

ループ内の冗長な演算の最小化

この例では、ループ内の冗長な演算を最小限にする方法を示します。ループ操作がループ インデックスに依存しない場合、ループ内でその操作を実行するのは冗長です。ループ内の単一の MATLAB® ステートメントで複数の演算を実行している場合、多くはこの冗長性を見落としています。たとえば、以下のコードでは、行列 B の逆行列は、ループ インデックスに依存していないのに、ループ内で 100 回計算されています。

for i=1:100
     C=C + inv(B)*A^i*B;
  end

このような冗長なループ操作を実行すると、不要な処理が生じることがあります。不要な処理を回避するには、ループ インデックスに依存しない限り、ループの外に演算を移動します。

  1. 以下のべき級数展開について、n 項の合計を計算する関数 SeriesFunc(A,B,n) を定義します。

    C=1+B1AB+B1A2B+...

      function C=SeriesFunc(A,B,n) 
    
    % Initialize C with a matrix having same dimensions as A
      C=zeros(size(A));
    
    % Perform the series sum
      for i=1:n
         C=C+inv(B)*A^i*B;
      end
    
  2. A および B の入力引数として渡される 4 行 4 列の行列を使用して SeriesFunc のコードを生成します。

    X = coder.typeof(zeros(4));
    codegen -config:lib -launchreport SeriesFunc -args {X,X,10}

    生成コードでは、ループ内で B の逆演算が n 回実行されます。ループ インデックスには依存しないため、ループの外で逆演算を 1 回実行した方がより無駄がありません。

  3. 以下のように SeriesFunc を変更します。

      function C=SeriesFunc(A,B,n) 
    
    % Initialize C with a matrix having same dimensions as A
      C=zeros(size(A));
    
    % Perform the inversion outside the loop
      inv_B=inv(B); 
    
    % Perform the series sum
      for i=1:n
         C=C+inv_B*A^i*B;
      end
    

    この手順では、B の逆演算を 1 回だけ実行し、生成コードの実行が速くなります。