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

Данные переменного размера являются данными, размер которых может измениться во время выполнения. Можно использовать MATLAB® Coder™, чтобы сгенерировать код C/C++ из кода MATLAB, который использует данные переменного размера. Поддержки MATLAB ограниченные и неограниченные данные переменного размера для генерации кода. Bounded variable-size data зафиксировал верхние границы. Эти данные могут быть выделены статически на стеке или динамически на куче. Unbounded variable-size data не имеет зафиксированных верхних границ. Эти данные должны быть выделены на куче. По умолчанию, для MEX и генерации кода C/C++, поддержка данных переменного размера включена, и динамическое выделение памяти включено для массивов переменного размера, размер которых больше или равен настраиваемому порогу.

Отключите поддержку данных Переменного Размера

По умолчанию, для MEX и генерации кода C/C++, поддержка данных переменного размера включена. Вы изменяете переменные настройки калибровки от диалогового окна настроек проекта, командной строки или использования диалоговых окон.

Используя приложение MATLAB Coder

  1. Чтобы открыть диалоговое окно Generate, на странице Generate Code, кликают по стреле Generate.

  2. Нажмите More Settings.

  3. На вкладке Memory выберите или очистите Enable variable-sizing.

В командной строке

  1. Создайте объект настройки для генерации кода. Например, для библиотеки:

    cfg = coder.config('lib');

  2. Установите EnableVariableSizing опция:

    cfg.EnableVariableSizing = false;

  3. Используя -config опция, передайте объект настройки codegen :

    codegen -config cfg foo
    

Управляйте динамическим выделением памяти

По умолчанию динамическое выделение памяти включено для массивов переменного размера, размер которых больше или равен настраиваемому порогу. Если вы отключаете поддержку данных переменного размера (см., Отключают Поддержку Данных Переменного Размера), вы также отключаете динамическое выделение памяти. Можно изменить настройки динамического выделения памяти от диалогового окна настроек проекта или командной строки.

Используя приложение MATLAB Coder

  1. Чтобы открыть диалоговое окно Generate, на странице Generate Code, кликают по стреле Generate.

  2. Нажмите More Settings.

  3. На вкладке Memory, набор Dynamic memory allocation к одной из следующих опций:

    УстановкаДействие
    NeverДинамическое выделение памяти отключено. Данные переменного размера выделяются статически на стеке.
    For all variable-sized arraysДинамическое выделение памяти включено для массивов переменного размера. Данные переменного размера выделяются динамически на куче.
    For arrays with max size at or above thresholdДинамическое выделение памяти включено для массивов переменного размера, размер которых больше или равен Dynamic memory allocation threshold. Массивы переменного размера, размер которых меньше этого порога, выделяются на стеке.

  4. Опционально, если вы устанавливаете Dynamic memory allocation на For arrays with maximum size at or above threshold, сконфигурируйте Dynamic memory allocation threshold, чтобы подстроить выделение памяти.

В командной строке

  1. Создайте объект настройки для генерации кода. Например, для MEX-функции:

    mexcfg = coder.config('mex');

  2. Установите DynamicMemoryAllocation опция:

    УстановкаДействие
    mexcfg.DynamicMemoryAllocation='Off';
    Динамическое выделение памяти отключено. Данные переменного размера выделяются статически на стеке.
    mexcfg.DynamicMemoryAllocation='AllVariableSizeArrays';
    Динамическое выделение памяти включено для массивов переменного размера. Данные переменного размера выделяются динамически на куче.
    mexcfg.DynamicMemoryAllocation='Threshold';
    Динамическое выделение памяти включено для массивов переменного размера, размер которых (в байтах) больше или равен значению, заданному с помощью DynamicMemoryAllocationThreshold параметр. Массивы переменного размера, размер которых меньше этого порога, выделяются на стеке.

  3. Опционально, если вы устанавливаете DynamicMemoryAllocation к 'Threshold', сконфигурируйте DynamicMemoryAllocationThreshold точно настраивать выделение памяти.

  4. Используя -config опция, передайте объект настройки codegen:

    codegen -config mexcfg foo
    

Генерация кода для функций MATLAB с данными Переменного Размера

Вот основной рабочий процесс, который сначала генерирует код MEX для проверки сгенерированного кода и затем генерирует автономный код после того, как вы удовлетворены результатом прототипа.

Чтобы работать через эти шаги с простым примером, смотрите, Генерируют Код для функции MATLAB, Которая Расширяет Вектор в Цикле

  1. В редакторе MATLAB добавьте директиву компиляции %#codegen во главе вашей функции.

    Эта директива:

    • Указывает, что вы намереваетесь сгенерировать код для алгоритма MATLAB

    • Включает регистрацию в Анализаторе кода MATLAB, чтобы обнаружить потенциальные ошибки во время генерации кода

  2. Решите проблемы, обнаруженные Анализатором кода.

    В некоторых случаях Анализатор кода MATLAB предупреждает вас, когда ваш код присваивает данные фиксированный размер, но позже выращивает данные, такой как присвоением или конкатенацией в цикле. Если те данные, как предполагается, отличаются по размеру во время выполнения, можно проигнорировать эти предупреждения.

  3. Сгенерируйте использование 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 выполняет проверку на этапе выполнения, чтобы сгенерировать ошибки, когда данные превышают верхние границы.

  4. Зафиксируйте ошибки несоответствия размера:

    ПричинаКак зафиксироватьДля получения дополнительной информации
    Вы пытаетесь изменить размер данных после того, как его размер был заблокирован.Объявите, что данные переменные измеренный.Смотрите диагностирование и фиксацию ошибок несоответствия размера.
  5. Зафиксируйте ошибки верхних границ

    ПричинаКак зафиксироватьДля получения дополнительной информации
    MATLAB не может определить или вычислить верхнюю границуЗадайте верхнюю границу.Верхние границы SeeSpecify для массивов Переменного Размера и диагностирования и фиксации ошибок несоответствия размера.
    MATLAB пытается вычислить верхнюю границу для неограниченных данных переменного размера.Если данные неограниченны, включите динамическое выделение памяти. Смотрите динамическое выделение памяти управления.
  6. Сгенерируйте код C/C++ с помощью codegen функция.

Сгенерируйте код для функции MATLAB, которая расширяет вектор в цикле

О функции MATLAB myuniquetol

Этот пример использует функциональный myuniquetol. Эта функция возвращается в векторном B версия входного вектора A, где элементы уникальны для в допуске tol друг из друга. В векторном B, absBiBJ))> 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

Шаг 1: добавьте директиву компиляции для генерации кода

Добавьте %#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

Шаг 2: решите проблемы, обнаруженные анализатором кода

Анализатор кода обнаруживает ту переменную B может изменить размер в for-цикл. Это выдает это предупреждение:

The variable 'B' appears to change size on every loop iteration.
Consider preallocating for speed.

В этой функции вы ожидаете векторный B расшириться в размере, потому что это добавляет значения из векторного A. Поэтому можно проигнорировать это предупреждение.

Шаг 3: сгенерируйте код MEX

Это - лучшая практика, чтобы сгенерировать код MEX, прежде чем вы сгенерируете код C/C++. Генерация кода MEX может идентифицировать проблемы генерации кода, которые более трудно обнаружить во время выполнения.

  1. Сгенерируйте MEX-функцию для myuniquetol:

    codegen -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}

     Что означают эти параметры командной строки?

    Генерация кода успешна. codegen не обнаруживает проблемы. В текущей папке, codegen генерирует MEX-функцию для myuniquetol и обеспечивает ссылку на отчет генерации кода.

  2. Щелкните по ссылке View report.

  3. В отчете генерации кода выберите вкладку Variables.

    Размер A 1x:100 потому что вы задали тот A переменный размер с верхней границей 100. Размер переменной B 1x:?, указание, что это - переменный размер без верхних границ.

Шаг 4: сгенерируйте код С

Сгенерируйте код С для входных параметров переменного размера. По умолчанию, codegen выделяет память статически для данных, размер которых меньше порога динамического выделения памяти 64 килобайтов. Если размер данных больше или равен порогу или неограничен, codegen выделяет память динамически на куче.

  1. Создайте параметр конфигурации для генерации библиотеки C:

    cfg=coder.config('lib');
    
  2. Дайте эту команду:

    codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}

    codegen генерирует статическую библиотеку в месте по умолчанию, codegen\lib\myuniquetol и обеспечивает ссылку на отчет генерации кода.

  3. Щелкните по ссылке View report.

  4. В списке сгенерированных файлов нажмите 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 Массивы в Сгенерированных Функциональных Интерфейсах.

Шаг 5: задайте верхнюю границу для выходного вектора

Вы указали что вход 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].

Шаг 6: измените порог динамического выделения памяти

На этом шаге вы уменьшаете порог динамического выделения памяти и генерируете код для входа, который превышает этот порог. Этот шаг указывает что второе измерение A имеет верхнюю границу 10000.

  1. Измените верхнюю границу 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

  2. Установите порог динамического выделения памяти к 4 килобайтам и сгенерируйте код где размер входа A превышает этот порог.

    cfg.DynamicMemoryAllocationThreshold=4096;
    codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 10000],1),coder.typeof(0)} 

  3. Просмотрите сгенерированный код в отчете. Поскольку максимальный размер A и B теперь превысьте порог динамического выделения памяти, codegen выделяет A и B динамически на куче. В сгенерированном коде, A и B имейте вводят emxArray_real_T.

    extern void myuniquetol(const emxArray_real_T *A, double tol, emxArray_real_T *B);

Похожие темы