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

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

Шаг 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.

  • 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].

Шаг 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);

Похожие темы