Сгенерируйте код С из символьных выражений с помощью приложения MATLAB Coder

В этом примере показано, как использовать приложение MATLAB ® Coder™ для создания статической библиотеки C из символьных выражений. Во-первых, вы работаете с символьными выражениями в Symbolic Math Toolbox™ и преобразуете символические выражения в развертываемую функцию MATLAB с помощью matlabFunction. Далее вы генерируете код С из функции MATLAB. Сгенерированный код C принимает входы, которые имеют фиксированный, предварительно назначенный размер, но можно также задать входы переменного размера во время генерации кода.

Этот пример следует шагам, описанным в Generate C Code при помощи MATLAB Coder App (MATLAB Coder), но обновляет шаги, чтобы сгенерировать функцию MATLAB из символического выражения. Также можно сгенерировать код С из функции MATLAB в командной строке MATLAB при помощи codegen (MATLAB Coder) команда. Учебное руководство по этому рабочему процессу смотрите в Генерация кода С в командной строке (MATLAB Coder).

Обратите внимание, что приложение MATLAB Coder не поддерживается в Online™ MATLAB. Чтобы сгенерировать код C/C + + в MATLAB Online, используйте codegen (MATLAB Coder) команда.

Сгенерируйте развертываемую функцию MATLAB из символьного выражения

Этот пример решает для собственных значений модели Hamiltonian:

H=(q-12-δ2ΩΩδ2+q+12),

где q, Ω, и δ являются параметрами гамильтониана.

Создайте символьные переменные q, Omega, и delta для представления параметров гамильтониана. Создайте символьную матрицу для гамильтониана.

syms q Omega delta
H = [(q-1)^2 - delta/2, Omega; Omega, (q+1)^2 + delta/2]
H = 

(q-12-δ2ΩΩδ2+q+12)[(q-1) ^ 2 - дельта/2, Омега; Омега, дельта/2 + (q + 1) ^ 2]

Найдите два собственных значений гамильтониана.

E = eig(H)
E = 

(q2-4Ω2+δ2+8δq+16q22+1q2+4Ω2+δ2+8δq+16q22+1)[q ^ 2 - sqrt (4 * Omega ^ sym (2) + delta ^ sym (2) + 8 * delta * q + 16 * q ^ 2 )/2 + 1; q ^ 2 + sqrt (4 * Omega ^ sym (2) + delta ^ sym (2) + 8 * delta * q + 16 * q ^ 2 )/2 + 1]

Далее преобразуйте два собственных значений E(1) и E(2) в файл функции MATLAB при помощи matlabFunction. Напишите получившуюся функцию, которая возвращает два элемента E1 и E2, в файл myEigenvalues.m. Задайте порядок входных параметров следующим [q Omega delta].

matlabFunction(E(1),E(2),'File','myEigenvalues', ...
    'Vars',[q Omega delta],'Outputs',{'E1','E2'});

Преобразованная функция в файле myEigenvalues.m может использоваться без Symbolic Math Toolbox. Файл MATLAB myEigenvalues.m содержит функцию myEigenvalues который реализует основной алгоритм в этом примере. Функция принимает q, Omega, и delta как входы, все они должны быть либо одинакового размера, либо скаляром. Затем он вычисляет два собственных значений как функцию от этих входов.

type myEigenvalues
function [E1,E2] = myEigenvalues(q,Omega,delta)
%MYEIGENVALUES
%    [E1,E2] = MYEIGENVALUES(Q,OMEGA,DELTA)

%    This function was generated by the Symbolic Math Toolbox version 8.7.
%    25-Apr-2021 12:42:52

t2 = Omega.^2;
t3 = delta.^2;
t4 = q.^2;
t6 = delta.*q.*8.0;
t5 = t2.*4.0;
t7 = t4.*1.6e+1;
t8 = t3+t5+t6+t7;
t9 = sqrt(t8);
t10 = t9./2.0;
E1 = t4-t10+1.0;
if nargout > 1
    E2 = t4+t10+1.0;
end

Запуск тестового скрипта MATLAB

Чтобы вычислить собственные значения для набора входов, создайте и запустите тестовый скрипт myTest.m в MATLAB. Тестовый скрипт задает входы со следующими размерами:

  • qGrid является 128-by- 256 матрица, которая представляет точки в двумерной (q,Ω) пространство.

  • OmegaGrid является 128-by- 256 матрица, которая представляет точки в двумерной (q,Ω) пространство.

  • delta является скаляром.

Затем скрипт вызывает функцию myEigenvalues.m для вычисления собственных значений. Выходные выходы отображают график собственных значений для этих входных значений. Ниже приведено содержимое скрипта myTest.m.

q = linspace(-2,2,256);
Omega = linspace(0,2,128);
delta = 1;

[qGrid,OmegaGrid] = meshgrid(q,Omega);
[E1,E2] = myEigenvalues(qGrid,OmegaGrid,delta);

surf(q,Omega,E1)
hold on;
surf(q,Omega,E2)
shading interp

Figure contains an axes. The axes contains 2 objects of type surface.

Сгенерируйте код С из функции MATLAB

Чтобы сделать код MATLAB подходящим для генерации кода, используйте Анализатор кода и Инструмент Code Generation Readiness. Анализатор кода в редакторе MATLAB постоянно проверяет ваш код при его вводе. Он сообщает о проблемах и рекомендует изменения для повышения эффективности и поддерживаемости. Code Generation Readiness Tool отображает код MATLAB для функций и функций, которые не поддерживаются для генерации кода.

Сделайте код MATLAB подходящим для генерации кода

  • Откройте myEigenvalues.m в редакторе MATLAB. После объявления функции добавьте %#codegen директива:

  • Индикатор сообщения Анализатор кода в правом верхнем углу редактора MATLAB зеленый. Анализатор не обнаружил ошибок, предупреждений или возможностей для улучшения кода. Дополнительные сведения об использовании анализатора кода см. в разделе Проверка кода на ошибки и предупреждения.

  • Сохраните файл. Теперь вы готовы скомпилировать код с помощью приложения MATLAB Coder.Здесь компиляция относится к генерации кода C/C + + из вашего кода MATLAB.

Откройте приложение MATLAB Coder и выберите исходные файлы

  • На вкладке Приложения панели инструментов MATLAB в разделе Генерация кода щелкните значок приложения MATLAB Coder. Приложение открывает страницу Select Source Files.

  • На странице Select Source Files введите или выберите имя функции точки входа myEigenvalues. Функция точки входа является функцией MATLAB верхнего уровня, из которой вы генерируете код. Приложение создает проект с именем по умолчанию myEigenvalues.prj в текущей папке.

  • Нажмите кнопку Далее (Next), чтобы перейти к шагу Задать входные типы (Define Input Types). Приложение запускает Анализатор Кода, который вы уже запускали на предыдущем шаге, и Инструмент Готовности Генерации Кода на функции точки входа. Если приложение определяет проблемы, оно открывает страницу Review Code Generation Readiness, на которой можно просмотреть и исправить проблемы. В этом примере, поскольку приложение не обнаруживает проблемы, он открывает страницу Задать входные типы. Для получения дополнительной информации смотрите Генерацию кода Инструмента готовности (MATLAB Coder).

Обратите внимание, что анализатор кода и инструмент готовности генерации кода могут обнаружить не все проблемы генерации кода. После устранения ошибок или предупреждений, которые эти два инструмента обнаруживают, сгенерируйте код с MATLAB Coder, чтобы определить, есть ли у вашего кода MATLAB другие проблемы с податливостью.

Определенные встроенные функции MATLAB и функции тулбокса, классы и системные объекты, поддерживаемые для генерации кода C/C + +, имеют определенные ограничения на генерацию кода. Эти ограничения и связанные с ними указания по применению перечислены в разделах Расширенные возможности (Extended Capabilities) соответствующих страниц с описанием. Для получения дополнительной информации смотрите Функции и Объекты, Поддерживаемые для Генерации кода C/C + + (MATLAB Coder).

Определите входные типы

Поскольку C использует статическое типирование, генератор кода должен определить класс, размер и сложность всех переменных в файлах MATLAB во время генерации кода, также известного как время компиляции. Поэтому необходимо задать свойства всех входных параметров функции точки входа. Чтобы задать входные свойства, можно:

  • Инструктируйте приложение автоматически определять входные свойства путем предоставления скрипта, который вызывает функции точки входа с выборочными входами.

  • Задайте свойства непосредственно.

В этом примере, чтобы задать свойства входов q, delta, и Omega, задайте тестовый файл myTest.m для генератора кода, используемого для автоматического определения типов:

  • Введите или выберите тестовый файл myTest.m в подсказке MATLAB.

  • Щелкните Автоопределить входные типы. Тестовый файл, myTest.m, вызывает функцию точки входа, myEigenvalues, с ожидаемыми типами входов. Приложение определяет, что вход q является double(128 x 256), а вход Omega является double(128 x 256), и входных delta является double(1 x 1).

  • Нажмите кнопку Далее, чтобы перейти к шагу Проверка проблем во время выполнения.

Проверяйте на наличие проблем во время выполнения

Шаг Проверка проблем во время выполнения генерирует MEX-функцию из функций точки входа, запускает MEX-функцию и сообщает о проблемах. Существует MEX-функция сгенерированного кода, который можно вызвать из MATLAB. Выполнение этого шага является наилучшей практикой, поскольку вы можете обнаруживать и исправлять ошибки времени выполнения, которые труднее диагностировать в сгенерированном коде C. По умолчанию MEX-функция включает проверку целостности памяти. Эти проверки выполняют ограничения массивов и проверку размерностей. Проверки обнаруживают нарушения целостности памяти в коде, сгенерированном для функций MATLAB. Для получения дополнительной информации смотрите Проверки во время выполнения управления (MATLAB Coder).

Чтобы преобразовать код MATLAB в эффективный исходный код C/C + +, генератор кода вводит оптимизации, которые в определенных ситуациях заставляют сгенерированный код вести себя по-другому, чем исходный исходный код. Смотрите Различия между сгенерированным кодом и кодом MATLAB (MATLAB Coder).

  • Чтобы открыть диалоговое окно Проверка проблем во время выполнения (если диалоговое окно не отображается автоматически), щелкните стрелу Проверка проблем.

  • В диалоговом окне Check for Run-Time Issues задайте тестовый файл или введите код, который вызывает функцию точки входа с примерами входов. В данном примере используйте тестовый файл myTest который использовался для определения типов входа.

  • Нажмите Проверить на проблемы. Приложение генерирует MEX-функцию, которая может запускаться внутри MATLAB. Этот шаг запускает тестовый скрипт myTest замена вызовов на myEigenvalues с вызовами сгенерированной MEX-функции, то есть [E1,E2] = myEigenvalues_mex(qGrid,OmegaGrid,delta). Сгенерированный файл MEX myEigenvalues_mex находится в папке work\codegen\lib\myEigenvalues (на платформах Microsoft ® Windows ®) или work/codegen/lib/myEigenvalues (на платформах Linux ® или Mac), где work - местоположение myEigenvalues.m и myTest.m. Если приложение обнаруживает проблемы во время генерации или выполнения MEX-функции, оно выдает предупреждения и сообщения об ошибке. Щелкните эти сообщения, чтобы перейти к проблемному коду и устранить проблему. В этом примере приложение не обнаруживает проблем.

  • По умолчанию приложение собирает количество выполнения линии. Эти счетчики помогают вам увидеть, насколько хорошо тестовый файл myTest.m выполнил myEigenvalues функция. Чтобы просмотреть счетчики выполнения линий, нажмите View MATLAB. Редактор приложений отображает маркированную цветом полосу слева от кода. Чтобы расширить подсветку цвета над кодом и увидеть счетчики выполнения линии, поместите курсор на полосу. Конкретный оттенок зеленого цвета указывает, что код выполняет только один вызов, чтобы вычислить собственные значения.

  • Нажмите кнопку Далее, чтобы перейти к шагу Сгенерировать код.

Сгенерируйте код С

  • Чтобы открыть диалоговое окно Сгенерировать (если диалоговое окно не отображается автоматически), щелкните стрелку Сгенерировать (Generate).

  • В диалоговом окне Generate установите тип Build на Static Library(.lib) и Language to C. Используйте значения по умолчанию для других настроек строения сборки проекта. Вместо генерации статической библиотеки C можно выбрать генерацию MEX-функции или других типов сборки C/C + +. Для типов сборки MEX и C/C + + доступны различные настройки проекта. При переключении между генерацией кода MEX и C/C + + проверьте выбранные настройки.

  • Щелкните Сгенерировать (Generate). MATLAB Coder генерирует автономную статическую библиотеку C, myEigenvalues, в папке work\codegen\lib\myEigenvalues. Папка work - местоположение myEigenvalues.m и myTest.m. Приложение MATLAB Coder указывает, когда генерация кода завершилась успешно. В нем отображаются исходные файлы MATLAB и сгенерированные выходные файлы в левой части страницы. На вкладке Переменные (Variables) отображается информация об исходных переменных MATLAB. На вкладке Target Build Log отображается журнал сборки, включая предупреждения и ошибки компилятора C/C + +. По умолчанию в окне кода отображается исходный файл кода C, myEigenvalues.c. Чтобы просмотреть другой файл, щелкните требуемое имя файла на панели Исходный код или Выходные файлы.

  • Щелкните Просмотр отчета (View Report), чтобы просмотреть отчет в окне Просмотр отчетов (Средство Просмотра). Если генератор кода обнаруживает ошибки или предупреждения во время генерации кода, отчет описывает проблемы и предоставляет ссылки на проблемный код MATLAB. Для получения дополнительной информации см. Отчеты генерации кода (MATLAB Coder).

  • Нажмите кнопку Далее, чтобы открыть страницу Готово рабочего процесса.

Просмотр страницы рабочего процесса конца

Страница Finish Workflow указывает, что генерация кода выполнена успешно. В нем содержатся сводные данные проекта и ссылки на сгенерированные выходы.

Сравнение сгенерированного кода C с оригинальным кодом MATLAB

Чтобы сравнить ваш сгенерированный код C с оригинальным кодом MATLAB, откройте файл C, myEigenvalues.c, и myEigenvalues.m файл в редакторе MATLAB.

Важная информация о сгенерированном коде C:

  • Сигнатура функции:

void myEigenvalues(const double q[32768], const double Omega[32768], double
                   delta, double E1[32768], double E2[32768])
  • const double q[32768] и const double Omega[32768] соответствует входу q и Omega в коде MATLAB. Размер q является 32768, что соответствует общему размеру (128 x 256) из примера входа, который вы использовали, когда вы сгенерировали код C/C + + из вашего кода MATLAB. То же самое относится и к входу Omega. В этом случае сгенерированный код использует одномерные массивы, чтобы представлять двумерные массивы в коде MATLAB.

  • Генератор кода сохраняет ваши имена функции и комментарии. Когда это возможно, генератор кода сохраняет ваши имена переменных. Обратите внимание, что если переменная в коде MATLAB установлена на постоянное значение, она не отображается как переменная в сгенерированном коде C. Вместо этого сгенерированный код C содержит значение переменной в виде литерала.

Сгенерируйте код С для входных параметров переменного размера

Функция C, которую вы сгенерировали для myEigenvalues.m может принимать только те входы, которые имеют тот же размер что и выборка входы, которые вы задали во время генерации кода. Однако входные массивы в соответствующую функцию MATLAB могут быть любого размера. В этой части примера вы генерируете код С из myEigenvalues.m который принимает входы переменного размера.

Предположим, что вам нужны размерности q, Omega, и delta в сгенерированном коде C, чтобы иметь следующие свойства:

  • Первая размерность обоих q и delta может варьироваться в размере до 100.

  • Второе измерение q и delta может варьироваться в размере до 400.

  • Omega является скаляром размера 1-by- 1.

Чтобы задать эти входные свойства с помощью MATLAB Coder, выполните следующие шаги:

  • На шаге Define Input Types задайте тестовый файл myTest.m и выберите «Автоопределить входные типы», как и прежде. Тестовый файл вызывает функцию точки входа, myEigenvalues.m, с ожидаемыми типами входов. Приложение определяет, что вход q является double(128 x 256), а вход Omega является double(128 x 256), и входных delta является double(1 x 1). Эти типы задают входы фиксированного размера.

  • Щелкните спецификации входного типа, чтобы изменить их. Вы можете задать размер переменной, до заданного предела, используя : префикс. Для примера, :100 указывает, что соответствующая размерность может варьироваться до 100. Измените тип для q на double(:100 x :400), для Omega на double(1 x 1), и для delta на double(:100 x :400).

Теперь можно сгенерировать код, выполнив те же шаги, что и ранее. Сигнатура функции для сгенерированного кода C в myEigenvalues.c теперь читает:

void myEigenvalues(const emxArray_real_T *q, double Omega, const emxArray_real_T
                   *delta, emxArray_real_T *E1, emxArray_real_T *E2)

Аргументы в сгенерированном коде соответствуют этим аргументам в исходной функции MATLAB:

  • emxArray_real_T*q - q входной параметр

  • Omega - Omega входной параметр

  • emxArray_real_T*delta - delta входной параметр

  • emxArray_real_T*E1 - E1 выходной аргумент

  • emxArray_real_T*E2 - E2 выходной аргумент

Теперь Код С состоит из структуры данных, называемой emxArray_real_T представлять массив, размер которого неизвестен и неограниченен во время компиляции. Для получения дополнительной информации смотрите Использование массивов C в Сгенерированных Функциональных Интерфейсах (MATLAB Coder).