原子のシミュレーションへの動的メモリ割り当ての使用
この例では、弾む原子のシミュレーションを実行し、ある反復回数後に結果を返す MATLAB® アルゴリズムにコードを生成する方法ついて説明します。アルゴリズムが受け入れる原子数に上限はないため、この例では動的メモリ割り当てを利用します。
前提条件
この例には必要条件はありません。
関数 run_atoms
について
関数 run_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;
すべての可変サイズの配列に対して動的メモリ割り当てを有効にします。
cfg.DynamicMemoryAllocationThreshold = 0;
サンプル入力の設定
入力パラメーター型に関する必要な情報がコンパイラに提供されるようにテンプレート構造体 '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 番目の引数は、スカラー double 値です。
-config cfg
は、ワークスペース変数 cfg
で定義される動的メモリ割り当てを有効にします。
codegen run_atoms -args {coder.typeof(atom, [1 Inf]),0,0} -config cfg -o run_atoms_mex
Code generation successful.
MEX 関数の実行
MEX 関数は、原子の空のリストが与えられると、約 1000 の反復ステップで 10000 の原子のシミュレーションを実行します。戻り値は、シミュレーション完了後のすべての原子の状態です。
atoms = repmat(atom,1,0); atoms = run_atoms_mex(atoms,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=1×10000 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=1×10000 struct array with fields:
x
y
vx
vy
スタンドアロン C コード ライブラリの生成
C ライブラリを生成するには、以下のようにライブラリの標準構成オブジェクトを作成します。
cfg = coder.config('lib');
すべての可変サイズの配列に対して動的メモリ割り当てを有効にします。
cfg.DynamicMemoryAllocationThreshold = 0;
MATLAB での既定のデータ型は double です。ただし、C コードでは通常は整数が使用されるため、ここでは原子の数と反復回数を表すサンプル値として int32
型の整数を渡します。
codegen run_atoms -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg
Code generation successful.
生成されたコードの検証
ライブラリを作成すると、フォルダー codegen/lib/run_atoms/
の中にコードが生成されます。このフォルダー内のコードは、自己完結しています。生成されたヘッダー ファイルとライブラリ ファイルがあれば、コンパイルされた C コードとのインターフェイスを取ることができます。
dir codegen/lib/run_atoms
. .. _clang-format buildInfo.mat codeInfo.mat codedescriptor.dmr compileInfo.mat examples interface rtGetInf.c rtGetInf.h rtGetInf.o rtGetNaN.c rtGetNaN.h rtGetNaN.o rt_nonfinite.c rt_nonfinite.h rt_nonfinite.o rtw_proj.tmw rtwtypes.h run_atoms.a run_atoms.c run_atoms.h run_atoms.o run_atoms_data.h run_atoms_emxAPI.c run_atoms_emxAPI.h run_atoms_emxAPI.o run_atoms_emxutil.c run_atoms_emxutil.h run_atoms_emxutil.o run_atoms_initialize.c run_atoms_initialize.h run_atoms_initialize.o run_atoms_rtw.mk run_atoms_terminate.c run_atoms_terminate.h run_atoms_terminate.o run_atoms_types.h
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/exe/run_atoms/run_atoms.h" /* The interface to EMX data structures. */ #include "codegen/exe/run_atoms/run_atoms_emxAPI.h" int main(int argc, char **argv) { FILE *fid; 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 a file */ fid = fopen("atoms_state.txt", "w"); for (i = 0; i < atoms->size[1]; i++) { fprintf(fid, "%f %f %f %f\n", atoms->data[i].x, atoms->data[i].y, atoms->data[i].vx, atoms->data[i].vy); } /* Close the file */ fclose(fid); /* Free memory */ emxDestroyArray_Atom(atoms); return(0); }
実行可能ファイル用の構成オブジェクトの作成
cfg = coder.config('exe');
cfg.DynamicMemoryAllocationThreshold = 0;
スタンドアロン実行可能ファイルの生成
関数 (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
Code generation successful.
実行可能ファイルの実行
シミュレーション完了後に、ファイル atoms_state.txt
を生成します。この TXT ファイルは 10000x4 の行列で、各行は原子の位置と速度 (x, y, vx, vy) であり、システム全体の現在の状態を表します。
system(['.' filesep 'run_atoms']);
状態の取得
実行可能ファイルを実行すると atoms_state.txt
が生成されました。次に、保存された行列から構造体配列を再作成します。
load atoms_state.txt -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);