Данные переменного размера являются данными, размер которых может измениться во время выполнения. Можно использовать 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 не может определить или вычислить верхнюю границу | Задайте верхнюю границу. | Верхние границы SeeSpecify для массивов Переменного Размера и диагностирования и фиксации ошибок несоответствия размера. |
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
и, потому что его максимальный размер является меньше, чем порог динамического выделения памяти по умолчанию 64k байтов, выделяет эту память статически. Сгенерированный код содержит:
double A_data[]
: определение A
.
int A_size[2]
: фактический размер входа.
Генератор кода решает, что B
является переменным размером с неизвестными верхними границами. Это представляет B
как emxArray_real_T
. MATLAB обеспечивает служебные функции для создания и взаимодействия с emxArrays
в вашем сгенерированном коде. Для получения дополнительной информации смотрите Использование C Массивы в Сгенерированных Функциональных Интерфейсах.
Вы указали, что вход A
является переменным размером с верхней границей 100
. Поэтому вы знаете, что вывод B
не может быть больше, чем элементы 100
.
Use 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);