Данные переменного размера - это данные, размер которых может измениться во время выполнения. Можно использовать MATLAB® Coder™ для генерации кода C/C + + из кода MATLAB, который использует данные переменного размера. MATLAB поддерживает ограниченные и неограниченные данные переменного размера для генерации кода. Bounded variable-size data имеет фиксированные верхние границы. Эти данные могут быть выделены статически в стеке или динамически в куче. Unbounded variable-size data не имеет фиксированных верхних границ. Эти данные должны быть выделены на куче. По умолчанию для генерации кода MEX и C/C + + включена поддержка данных переменного размера и включено динамическое выделение памяти для массивов переменного размера, размер которых больше или равен конфигурируемому порогу.
По умолчанию для генерации кода MEX и C/C + + включена поддержка данных переменного размера. Вы изменяете параметры переменных размеров из диалогового окна параметров проекта, командной строки или с помощью диалоговых окон.
Чтобы открыть диалоговое окно Generate, на странице Generate Code щелкните стрелу Generate.
Нажмите More Settings.
На вкладке Memory выберите или очистите Enable variable-sizing.
Создайте объект строения для генерации кода. Для примера, для библиотеки:
cfg = coder.config('lib');
Установите EnableVariableSizing
опция:
cfg.EnableVariableSizing = false;
Использование -config
опция, передайте объект строения в codegen
:
codegen -config cfg foo
По умолчанию динамическое выделение памяти разрешено для массивов переменного размера, размер которых больше или равен конфигурируемому порогу. Если вы отключаете поддержку данных переменного размера (см. «Отключить поддержку данных переменного размера»), вы также отключаете динамическое выделение памяти. Вы можете изменить настройки динамического выделения памяти из диалогового окна параметров проекта или командной строки.
Чтобы открыть диалоговое окно Generate, на странице Generate Code щелкните стрелу Generate.
Нажмите More Settings.
На вкладке Memory установите Dynamic memory allocation одну из следующих опций:
Настройка | Действие |
---|---|
Never | Динамическое выделение памяти отключено. Данные переменного размера выделяются статически в стеке. |
For all variable-sized arrays | Динамическое выделение памяти включено для массивов переменного размера. Данные переменного размера распределяются динамически на куче. |
For arrays with max size at or above threshold | Динамическое выделение памяти разрешено для массивов переменного размера, размер которых больше или равен Dynamic memory allocation threshold. Массивы переменного размера, размер которых меньше этого порога, выделяются в стеке. |
Если вы задаете Dynamic memory allocation равным For arrays with maximum size at or above threshold
, сконфигурируйте Dynamic memory allocation threshold, чтобы настроить выделение памяти.
Создайте объект строения для генерации кода. Для примера, для MEX-функции:
mexcfg = coder.config('mex');
Установите DynamicMemoryAllocation
опция:
Настройка | Действие |
---|---|
mexcfg.DynamicMemoryAllocation='Off'; | Динамическое выделение памяти отключено. Данные переменного размера выделяются статически в стеке. |
mexcfg.DynamicMemoryAllocation='AllVariableSizeArrays'; | Динамическое выделение памяти включено для массивов переменного размера. Данные переменного размера распределяются динамически на куче. |
mexcfg.DynamicMemoryAllocation='Threshold'; | Динамическое выделение памяти разрешено для массивов переменного размера, размер которых (в байтах) больше или равен значению, заданному с помощью DynamicMemoryAllocationThreshold параметр. Массивы переменного размера, размер которых меньше этого порога, выделяются в стеке. |
Опционально, если вы задаете DynamicMemoryAllocation
на 'Threshold'
, сконфигурируйте DynamicMemoryAllocationThreshold
для точной настройки выделения памяти.
Использование -config
опция, передайте объект строения в codegen
:
codegen -config mexcfg foo
Вот базовый рабочий процесс, который сначала генерирует код MEX для проверки сгенерированного кода, а затем генерирует автономный код после того, как вы удовлетворены результатом прототипа.
Чтобы пройти через эти шаги с простым примером, см. «Генерация кода для функции MATLAB, которая расширяет вектор в цикле»
В РЕДАКТОРА MATLAB добавьте директиву компиляции %#codegen
в верхней части вашей функции.
Эта директива:
Указывает, что вы намерены сгенерировать код для алгоритма MATLAB
Включает проверку в анализаторе кода MATLAB, чтобы обнаружить потенциальные ошибки во время генерации кода
Устраните проблемы, обнаруженные анализатором кода.
В некоторых случаях анализатор КОДА MATLAB предупреждает вас, когда ваш код присваивает данным фиксированный размер, но позже увеличивает данные, например, путем назначения или конкатенации в цикле. Если эти данные должны варьироваться в размере во время исполнения, можно игнорировать эти предупреждения.
Сгенерируйте MEX-функцию используя codegen
для проверки сгенерированного кода. Используйте следующие опции командной строки:
-args {coder.typeof...}
если у вас есть входы переменного размера
-report
чтобы сгенерировать отчет генерации кода
Для примера:
codegen -report foo -args {coder.typeof(0,[2 4],1)}
coder.typeof
чтобы задать один вход переменного размера для функции foo
. Первый аргумент, 0
, указывает тип входных данных (double
) и сложности (real
). Второй аргумент, [2 4]
, указывает размер, матрица с двумя размерностями. Третий аргумент, 1
, указывает, что вход имеет переменный размер. Верхняя граница равна 2 для первой размерности и 4 для второго измерения.Примечание
Во время компиляции, codegen
обнаруживает переменные и поля структуры, которые изменяют размер после их определения, и сообщает об этих вхождениях как об ошибках. В сложение, codegen
выполняет проверку во время выполнения, чтобы сгенерировать ошибки, когда данные превышают верхние границы.
Исправьте ошибки несоответствия размера:
Причина | Как исправить | Для получения дополнительной информации |
---|---|---|
Вы пытаетесь изменить размер данных после того, как его размер был заблокирован. | Объявите данные переменным размером. | См. «Диагностика и исправление ошибок несоответствия размеров». |
Исправьте ошибки верхних границ
Причина | Как исправить | Для получения дополнительной информации |
---|---|---|
MATLAB не может определить или вычислить верхнюю границу | Задайте верхнюю границу. | См. Определение верхних границ для массивов переменного размера и диагностика и исправление ошибок несоответствия размеров. |
MATLAB пытается вычислить верхнюю границу для неограниченных данных переменного размера. | Если данные не ограничены, включите динамическое выделение памяти. | См. Раздел «Управление динамическим выделением памяти» |
Сгенерируйте код C/C + + с помощью codegen
функция.
Этот пример использует функцию myuniquetol
. Эта функция возвращается в векторном B
версию входа вектора A
, где элементы являются уникальными для в пределах допуска tol
друг от друга. В векторных B
, abs
(B
(i
) - B
(j
))> tol
для всех i
и j
. Первоначально предположим, что входной вектор A
может хранить до 100 элементов.
function B = myuniquetol(A, tol) A = sort(A); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
Добавьте %#codegen
директива компиляции в верхней части функции:
function B = myuniquetol(A, tol) %#codegen A = sort(A); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
Анализатор кода обнаруживает эту переменную B
может изменить размер for-
цикл. Оно выдает это предупреждение:
The variable 'B' appears to change size on every loop iteration. Consider preallocating for speed.
В этой функции вы ожидаете векторную B
чтобы расширить размер, поскольку он добавляет значения из векторных A
. Поэтому можно игнорировать это предупреждение.
Это лучшая практика, чтобы сгенерировать код MEX, прежде чем вы генерируете код C/C + +. Генерация кода MEX может идентифицировать проблемы генерации кода, которые труднее обнаружить во время исполнения.
Сгенерируйте MEX-функцию для myuniquetol
:
codegen -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
Что означают эти опции командной строки?
Генерация кода выполнена успешно. codegen
не обнаруживает проблемы. В текущей папке, codegen
генерирует MEX-функцию для myuniquetol
и предоставляет ссылку на отчет генерации кода.
Щелкните ссылку View report.
В отчете генерации кода выберите вкладку Variables.
Размер A
является 1x:100
потому что вы указали, что A
- размер переменной с верхней границей 100
. Размер переменной B
является 1x:?
, что указывает, что это размер переменной без верхних границ.
Сгенерируйте код С для входов переменного размера. По умолчанию, codegen
статически выделяет память для данных, размер которых меньше динамического порога выделения памяти в 64 килобайта. Если размер данных больше или равен порогу или не ограничен, codegen
динамически выделяет память на куче.
Создайте опцию строения для генерации библиотеки на C:
cfg=coder.config('lib');
Выполните следующую команду:
codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
codegen
генерирует статическую библиотеку в расположении по умолчанию, codegen\lib\myuniquetol
и предоставляет ссылку на отчет генерации кода.
Щелкните ссылку View report.
В списке сгенерированных файлов нажмите myuniquetol.h
.
Объявление функции:
extern void myuniquetol(const double A_data[], const int A_size[2], double tol, emxArray_real_T *B);
codegen
вычисляет размер A
и, поскольку его максимальный размер меньше порога динамического выделения памяти по умолчанию в 64 тыс. байт, выделяет эту память статически. Сгенерированный код содержит:
double A_data[]
определение A
.
int A_size[2]
: фактический размер входа.
Генератор кода определяет, что B
- размер переменной с неизвестными верхними границами. Он представляет B
как emxArray_real_T
. MATLAB обеспечивает служебные функции для создания и взаимодействия с emxArrays
в вашем сгенерированном коде. Для получения дополнительной информации смотрите Использование массивов C в Сгенерированных Функциональных Интерфейсах.
Вы указали, что вход A
- размер переменной с верхней границей 100
. Поэтому вы знаете, что выход B
не может быть больше 100
элементы.
Использовать coder.varsize
чтобы указать, что B
- размер переменной с верхней границей 100
.
function B = myuniquetol(A, tol) %#codegen A = sort(A); coder.varsize('B', [1 100], [0 1]); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
Сгенерируйте код.
codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
Объявление функции:
extern void myuniquetol(const double A_data[], const int A_size[2], double tol, double B_data[], int B_size[2]);
Генератор кода статически выделяет память для B
. Он хранит размер B
в int B_size[2]
.
На этом этапе вы уменьшаете порог динамического выделения памяти и генерируете код для входа, который превышает этот порог. Этот шаг задает, что второе измерение A
имеет верхнюю границу 10000
.
Измените верхнюю границу B
чтобы соответствовать верхней границе A
.
function B = myuniquetol(A, tol) %#codegen A = sort(A); coder.varsize('B', [1 10000], [0 1]); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
Установите динамический порог выделения памяти в 4 килобайта и сгенерируйте код, где вход размер A
превышает этот порог.
cfg.DynamicMemoryAllocationThreshold=4096; codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 10000],1),coder.typeof(0)}
Просмотрите сгенерированный код в отчете. Потому что максимальный размер A
и B
теперь превысите динамический порог выделения памяти, codegen
выделяет A
и B
динамически на куче. В сгенерированном коде A
и B
иметь тип emxArray_real_T
.
extern void myuniquetol(const emxArray_real_T *A, double tol, emxArray_real_T *B);