Main Content

MATLAB Function ブロックを含むモデル用の行優先のコードの生成

プログラミング言語および環境は、すべてのデータに対して単一の配列レイアウトを想定します。MATLAB® と Fortran は、既定で列優先のレイアウトを使用しますが、C と C++ は行優先のレイアウトを使用します。Simulink® Coder™ では、行優先のレイアウトまたは列優先のレイアウトを使用する C/C++ コードを生成できます。

行優先のコード生成の詳細については、行列および配列のコード生成を参照してください。

MATLAB Function ブロックは、MATLAB 言語を使用して Simulink モデルにカスタム機能を定義できるようにします。行優先のデータまたは列優先のデータを使用することで、MATLAB Function ブロックを含むモデルについて行優先のコードを生成できます。MATLAB Function ブロックの詳細については、Simulink での MATLAB Function ブロックを使用した MATLAB 関数の実装を参照してください。

既定では、コード ジェネレーターは列優先のコードを生成します。C/C++ コードの生成について、[配列のレイアウト] モデル コンフィギュレーション パラメーターを使用することで、配列のレイアウトをモデル レベルで指定できます。このパラメーターを [行優先] に設定すると、モデルで行優先のコード生成が有効になります。モデル内の MATLAB Function ブロックで行優先のコード生成を有効にするには、ブロック内の関数レベルで関数 coder.rowMajor を使用します。

行優先のコード生成

一部のアルゴリズムでは、行優先のレイアウトの方がメモリ アクセスの効率が向上します。行優先の配列レイアウトを使用するモデルのコードを生成し、行優先データのアルゴリズムを使用する MATLAB Function ブロックがそのモデルに含まれる場合、効率的なコードが得られます。

  1. モデル例 ex_row_major_MLFB について考えます。

    このモデルには、[5 4] 行列をもつ Constant ブロックが含まれます。行列を指定するため、[定数値] を以下に設定します。

    reshape(1:20,5,4)
    Inport ブロックも、[5 4] 行列を指定します。行列を指定するため、[端子の次元][5 4] に設定します。

  2. [コンフィギュレーション パラメーター] ダイアログ ボックスで、[配列のレイアウト][行優先] に設定します。

  3. 行列加算の関数 addMatrix を記述します。特に指定していない限り、MATLAB Function ブロックは、モデル コンフィギュレーション パラメーター [配列のレイアウト] から配列のレイアウト設定を継承します。

    オプションで、coder.rowMajor を使用して、MATLAB Function ブロックの配列のレイアウトを行優先のレイアウトに明示的に設定できます。

    function S  = addMatrix(A,B) 
    S = zeros(size(A));
    for row = 1:size(A,1) 
       for col = 1:size(A,2)  
           S(row,col) = A(row,col) + B(row,col);
       end
    end

  4. モデルのコードを生成します。[C コード] タブで [ビルド] をクリックします。

コード ジェネレーターは、以下の C コードを生成します。

for (b_row = 0; b_row < 5; b_row++) {
    for (b_col = 0; b_col < 4; b_col++) {
      rtb_S_tmp = (b_row << 2) + b_col;
      rtb_S[rtb_S_tmp] = ex_row_major_MLFB_P.Constant_Value[rtb_S_tmp] +
        ex_row_major_MLFB_U.Inport1[rtb_S_tmp];
    }
  }
生成されたコードには for ループが 2 つあります。1 つ目の for ループは行にアクセスし、2 つ目の for ループは列にアクセスします。MATLAB Function ブロックとモデルの配列のレイアウトが同一のとき、転置や変換が必要ないため、生成されたコードは効率的になります。

優先形式混在のコード生成

行優先のデータを扱うモデルと、列優先のデータを扱う MATLAB Function ブロックがある場合、優先形式混在のコードを生成できます。列優先のレイアウトを使用するモデルのコードを生成するとき、そのモデルに行優先のレイアウトを使用する MATLAB Function ブロックが含まれる場合、コード ジェネレーターは必要に応じてブロック入力データを行優先に変換し、ブロック出力データを列優先データに再変換します。列優先のデータを扱うモデルと、行優先のデータを扱う MATLAB Function ブロックがある場合も、優先形式混在のコードを生成できます。

配列レイアウトの変換は、パフォーマンスに影響を与えることがあります。

  1. モデル例 ex_row_major_MLFB を考えます。モデル例の詳細については、行優先のコード生成を参照してください。

    [コンフィギュレーション パラメーター] ダイアログ ボックスで、[配列のレイアウト][行優先] に設定します。

  2. 関数 coder.columnMajor を使用して、MATLAB Function ブロックの関数 addMatrix を列優先のデータに更新します。

    function S  = addMatrix(A,B) 
    coder.columnMajor;
    S = zeros(size(A));
    for row = 1:size(A,1) 
       for col = 1:size(A,2)  
           S(row,col) = A(row,col) + B(row,col);
       end
    end
    MATLAB Function ブロックを使用して、優先形式混在のコードを生成できます。この場合、モデルは行優先の配列レイアウトに構成し、MATLAB Function ブロックは列優先の配列レイアウトに構成します。

  3. モデルのコードを生成します。[C コード] タブで [ビルド] をクリックします。

コード ジェネレーターは、以下の C コードを生成します。

for (b_row = 0; b_row < 4; b_row++) {
    for (b_col = 0; b_col < 5; b_col++) {
      B_tmp = (b_col << 2) + b_row;
      B_tmp_0 = b_col + 5 * b_row;
      B[B_tmp_0] = ex_row_major_MLFB_19b_U.Inport1[B_tmp];
      A[B_tmp_0] = ex_row_major_MLFB_19b_P.Constant_Value[B_tmp];
    }
  }

  for (b_row = 0; b_row < 5; b_row++) {
    /* Outport: '<Root>/Outport' */
    for (b_col = 0; b_col < 4; b_col++) {
      B_tmp = 5 * b_col + b_row;
      ex_row_major_MLFB_19b_Y.Outport[b_col + (b_row << 2)] = A[B_tmp] + B[B_tmp];
    }
MATLAB Function ブロックへの入力は、行優先の環境に存在します。MATLAB Function ブロックは列優先のレイアウトであるため、コード ジェネレーターは、ブロックに送る前に、入力に変換処理を実行します。MATLAB Function ブロックのアルゴリズムを処理した後、コード ジェネレーターはデータを Outport に渡す前に行優先のデータに再変換します。

関連するトピック