Этот пример показывает, как сгенерировать код для алгоритма MATLAB ®, который запускает симуляцию прыгающих «атомов» и возвращает результат после ряда итераций. Нет верхних границ количества атомов, которые принимает алгоритм, поэтому этот пример использует преимущества динамического выделения памяти.
Для этого примера нет необходимых условий.
run_atoms
ФункцияThe 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; % Enable dynamic memory allocation for variable size matrices. cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';
Создайте структуру шаблона 'Atom', чтобы предоставить компилятору необходимую информацию о типах входных параметров. Атом является структурой с четырьмя полями (x, y, vx, vy), задающими положение и скорость в Декартовых координатах.
atom = struct('x', 0, 'y', 0, 'vx', 0, 'vy', 0);
Используйте команду codegen
со следующими аргументами:
-args {coder.typeof(atom, [1 Inf]),0,0}
указывает, что первый аргумент является вектором-строкой атомов, где количество столбцов потенциально бесконечно. Второй и третий аргументы являются скалярными двойными значениями.
-config cfg
включает динамическое выделение памяти, заданное переменной рабочей области cfg
codegen run_atoms -args {coder.typeof(atom, [1 Inf]),0,0} -config cfg -o run_atoms_mex
Code generation successful.
MEX-функция моделирует 10000 атомов приблизительно за 1000 шагов итерации, учитывая пустой список атомов. Значение возврата является состоянием всех атомов после завершения симуляции.
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
Продолжите симуляцию с помощью еще 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, создайте стандартный объект строения для библиотек:
cfg = coder.config('lib');
Включите динамическое выделение памяти
cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';
В MATLAB тип данных по умолчанию double. Однако в коде С обычно используются целые числа, поэтому передайте int32
целочисленные значения примера для представления количества атомов и итераций.
codegen run_atoms -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg
Code generation successful.
При создании библиотеки код генерируется в папке codegen/lib/run_atoms/
. Код в этой папке является автономным. Для взаимодействия с скомпилированным кодом С вам нужны только сгенерированные заголовочные файлы и файл библиотеки.
dir codegen/lib/run_atoms
. rtGetNaN.h run_atoms_emxAPI.h .. rtGetNaN.o run_atoms_emxAPI.o .gitignore rt_nonfinite.c run_atoms_emxutil.c _clang-format rt_nonfinite.h run_atoms_emxutil.h buildInfo.mat rt_nonfinite.o run_atoms_emxutil.o codeInfo.mat rtw_proj.tmw run_atoms_initialize.c codedescriptor.dmr rtwtypes.h run_atoms_initialize.h compileInfo.mat run_atoms.a run_atoms_initialize.o defines.txt run_atoms.c run_atoms_rtw.mk examples run_atoms.h run_atoms_terminate.c interface run_atoms.o run_atoms_terminate.h rtGetInf.c run_atoms_data.c run_atoms_terminate.o rtGetInf.h run_atoms_data.h run_atoms_types.h rtGetInf.o run_atoms_data.o rtGetNaN.c run_atoms_emxAPI.c
Как правило, основной функцией является зависящий от платформы код, который выполняет визуализацию или некоторую другую обработку. В этом примере чистая функция 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.DynamicMemoryAllocation = 'AllVariableSizeArrays';
Вы должны передать функцию (run_atoms.m
) а также пользовательский код С (run_atoms_main.c
) The codegen
команда автоматически генерирует код C из кода MATLAB, затем вызывает компилятор C, чтобы связать этот сгенерированный код с пользовательским кодом C (run_atoms_main.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);