Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

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

この例では、弾む原子のシミュレーションを実行し、ある反復回数後に結果を返す 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);

Figure MATLAB Coder Atoms contains an axes object. The axes object contains an object of type image.