Данные переменного размера являются данными, размер которых может измениться во время выполнения. Можно использовать 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
элементы.
Использование 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);