MATLAB Coder

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

原子のシミュレーションへの動的なメモリ割り当ての使用

この例では、弾む原子のシミュレーションを実行し、ある反復回数後に結果を返す MATLAB アルゴリズムにコードを生成する方法ついて説明します。アルゴリズムが受け入れる原子数に上限はないため、この例では動的なメモリ割り当てを利用します。

必要条件

この例には必要条件はありません。

新規フォルダーの作成と関連ファイルのコピー

以下のコードは、現在の作業フォルダー (pwd) 内にフォルダーを作成します。この新規フォルダーには、この例に関連するファイルのみが含められます。現在のフォルダーに影響を与えたくない (またはこのフォルダーにファイルを生成できない) 場合は、作業フォルダーを変更する必要があります。

コマンドの実行: 新規フォルダーの作成と関連ファイルのコピー

coderdemo_setup('coderdemo_atoms');

関数 'run_atoms' について

関数 run_atoms.mrun_atoms.m は、弾む原子のシミュレーションを実行します (重力とエネルギー損失を考慮します)。

help run_atoms
  atoms = run_atoms(atoms,n)
  atoms = run_atoms(atoms,n,iter)
  Where 'atoms' the initial and final state of atoms (can be empty)
        'n' is the number of atoms to simulate.
        'iter' is the number of iterations for the simulation
           (if omitted it is defaulted to 3000 iterations.)

コード生成オプションの設定

コード生成コンフィギュレーション オブジェクトを作成します。

cfg = coder.config;
% Enable dynamic memory allocation for variable size matrices.
cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';

サンプル入力の設定

入力パラメーター型に関する必要な情報がコンパイラに提供されるようにテンプレート構造体 'Atom' を作成します。原子は、直交座標で位置と速度を指定する 4 つのフィールド (x、y、vx、vy) をもつ構造です。

atom = struct('x', 0, 'y', 0, 'vx', 0, 'vy', 0);

テスト用の MEX 関数の生成

以下の引数と共に 'codegen' コマンドを使用します。

引数 '-args {coder.typeof(atom, [1 Inf]),0,0}' は、最初の引数が原子の行ベクトルで、列数が無限となる場合があることを示します。2 番目と 3 番目の引数は、スカラー倍精度値です。

'-config cfg' は、ワークスペース変数 cfg で定義される動的なメモリ割り当てを有効にします。

codegen run_atoms -args {coder.typeof(atom, [1 Inf]),0,0} -config cfg -o run_atoms_mex

MEX 関数の実行

MEX 関数は、原子の空のリストが与えられると、約 1000 の反復ステップで 10000 の原子のシミュレーションを実行します。戻り値は、シミュレーション完了後のすべての原子の状態です。

atoms = run_atoms_mex([],10000,1000)
Iteration: 50
Iteration: 100
Iteration: 150
Iteration: 200
Iteration: 250
Iteration: 300
Iteration: 350
Iteration: 400
Iteration: 450
Iteration: 500
Iteration: 550
Iteration: 600
Iteration: 650
Iteration: 700
Iteration: 750
Iteration: 800
Iteration: 850
Iteration: 900
Iteration: 950
Iteration: 1000
Completed iterations: 1000

atoms = 

1x10000 struct array with fields:

    x
    y
    vx
    vy

MEX 関数の再実行

500 の反復ステップを実行してシミュレーションを続行します。

atoms = run_atoms_mex(atoms,10000,500)
Iteration: 50
Iteration: 100
Iteration: 150
Iteration: 200
Iteration: 250
Iteration: 300
Iteration: 350
Iteration: 400
Iteration: 450
Iteration: 500
Completed iterations: 500

atoms = 

1x10000 struct array with fields:

    x
    y
    vx
    vy

スタンドアロン C コード ライブラリの生成

C ライブラリを生成するには、以下のようにライブラリの標準コンフィギュレーション オブジェクトを作成します。

cfg = coder.config('lib');

動的なメモリ割り当てを有効にします。

cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';

MATLAB での既定のデータ型は double です。ただし、C コードでは通常は整数が使用されるため、ここでは原子の数と反復回数を表すサンプル値として int32 型の整数を渡します。

codegen run_atoms -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg

生成されたコードの検証

ライブラリを作成すると、フォルダー codegen/lib/run_atoms/ の中にコードが生成されます。このフォルダー内のコードは、自己完結しています。生成されたヘッダー ファイルとライブラリ ファイルがあれば、コンパイルされた C コードとのインターフェイスを取ることができます。

dir codegen/lib/run_atoms
.                       rt_nonfinite.h          run_atoms_emxutil.h     
..                      rt_nonfinite.o          run_atoms_emxutil.o     
buildInfo.mat           rtw_proj.tmw            run_atoms_initialize.c  
codeInfo.mat            rtwtypes.h              run_atoms_initialize.h  
interface               run_atoms.a             run_atoms_initialize.o  
rtGetInf.c              run_atoms.c             run_atoms_ref.rsp       
rtGetInf.h              run_atoms.h             run_atoms_rtw.mk        
rtGetInf.o              run_atoms.o             run_atoms_terminate.c   
rtGetNaN.c              run_atoms_emxAPI.c      run_atoms_terminate.h   
rtGetNaN.h              run_atoms_emxAPI.h      run_atoms_terminate.o   
rtGetNaN.o              run_atoms_emxAPI.o      run_atoms_types.h       
rt_nonfinite.c          run_atoms_emxutil.c     

C の Main 関数の作成

通常、main 関数はレンダリングまたはその他の処理を実行するプラットフォームに依存したコードです。この例では、純粋な ANSI-C 関数を使用して、原子のシミュレーションの最終的な状態 (実行時) を含んでいるファイル 'run_atoms_state.m' を生成します。

type run_atoms_main.c
/* Include standard C libraries */
#include <stdio.h>

/* The interface to the main function we compiled. */
#include "codegen/lib/run_atoms/run_atoms.h"

/* The interface to EMX data structures. */
#include "codegen/lib/run_atoms/run_atoms_emxAPI.h"

int main(int argc, char **argv)
{
    int i;
    emxArray_Atom *atoms;
 
    /* Main arguments unused */
    (void) argc;
    (void) argv;
    
    /* Initially create an empty row vector of atoms (1 row, 0 columns) */
    atoms = emxCreate_Atom(1, 0);
    
    /* Call the function to simulate 10000 atoms in 1000 iteration steps */
    run_atoms(atoms, 10000, 1000);
    
    /* Call the function again to do another 500 iteration steps */
    run_atoms(atoms, 10000, 500);
    
    /* Print the result to standard output */
    for (i = 0; i < atoms->size[1]; i++) {
        printf("%f %f %f %f\n",
            atoms->data[i].x, atoms->data[i].y, atoms->data[i].vx, atoms->data[i].vy);
    }
    
    /* Free memory */
    emxDestroyArray_Atom(atoms);
    return(0);
}

実行ファイル用のコンフィギュレーション オブジェクトの作成

cfg = coder.config('exe');
cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';

スタンドアロン実行ファイルの生成

関数 (run_atoms.m) とカスタム C コード (run_atoms_main.c) を渡さなければなりません。codegen コマンドは、最初に MATLAB から C コードを自動的に生成します。次に、生成されたこのコードをカスタム C コード (run_atoms_main.c) とまとめるために C コンパイラを起動します。

codegen run_atoms run_atoms_main.c -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg

実行ファイルの実行

シミュレーション完了後に、ファイル 'atoms_state.mat' を生成します。この MAT ファイルは 10000x4 の行列で、各行は原子の位置と速度 (x, y, vx, vy) であり、システム全体の現在の状態を表します。

[~,atoms_data] = system(['.' filesep 'run_atoms']);
fh = fopen('atoms_state.mat', 'w');
fprintf(fh, '%s', atoms_data);
fclose(fh);

状態の取得

実行ファイルを実行すると 'atoms_state.mat' が生成されます。次に、保存された行列から構造体配列を再作成します。

load atoms_state.mat -ascii
clear atoms
for i = 1:size(atoms_state,1)
    atoms(1,i).x  = atoms_state(i,1);
    atoms(1,i).y  = atoms_state(i,2);
    atoms(1,i).vx = atoms_state(i,3);
    atoms(1,i).vy = atoms_state(i,4);
end

状態のレンダリング

反復回数がゼロの 'run_atoms_mex' をレンダリング専用に呼び出します。

run_atoms_mex(atoms, 10000, 0);

クリーン アップ

ファイルを削除して元のフォルダーに戻ります。

コマンドの実行: クリーンアップ

if ispc
    delete run_atoms.exe
else
    delete run_atoms
end
delete atoms_state.mat
cleanup