exponenta event banner

Создание кода для данных переменного размера

Данные переменного размера - это данные, размер которых может измениться во время выполнения. Для создания кода C/C + + из кода MATLAB, использующего данные переменного размера, можно использовать MATLAB ® Coder™. MATLAB поддерживает ограниченные и неограниченные данные переменного размера для генерации кода. Ограниченные данные переменного размера имеют фиксированные верхние границы. Эти данные могут распределяться статически в стеке или динамически в куче. Неограниченные данные переменного размера не имеют фиксированных верхних границ. Эти данные должны быть распределены в куче. По умолчанию для генерации кода MEX и C/C + + включена поддержка данных переменного размера, а динамическое выделение памяти включено для массивов переменного размера, размер которых больше или равен настраиваемому порогу.

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

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

Использование приложения кодера MATLAB

  1. Чтобы открыть диалоговое окно «Генерация», на странице «Генерация кода» щелкните стрелку «Генерация».

  2. Щелкните Дополнительные параметры.

  3. На вкладке Память (Memory) выберите или снимите флажок Включить переменный размер (Enable variable-size).

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

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

    cfg = coder.config('lib');

  2. Установите EnableVariableSizing вариант:

    cfg.EnableVariableSizing = false;

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

    codegen -config cfg foo
    

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

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

Использование приложения кодера MATLAB

  1. Чтобы открыть диалоговое окно «Генерация», на странице «Генерация кода» щелкните стрелку «Генерация».

  2. Щелкните Дополнительные параметры.

  3. На вкладке Память установите для параметра Динамическое выделение памяти одну из следующих опций.

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

  4. При необходимости установите для параметра Динамическое выделение памяти значение For arrays with maximum size at or above 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 не может определить или вычислить верхнюю границуУкажите верхнюю границу.См. раздел Указание верхних границ для массивов переменного размера и Диагностика и исправление ошибок несоответствия размеров.
    MATLAB пытается вычислить верхнюю границу для неограниченных данных переменного размера.Если данные являются неограниченными, включите динамическое выделение памяти. См. раздел Управление динамическим распределением памяти.
  6. Создание кода C/C + + с помощью codegen функция.

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

Сведения о функции Myuniquetol MATLAB

В этом примере используется функция 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. Щелкните ссылку Просмотр отчета.

  3. В отчете о создании кода выберите закладку Переменные.

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

Шаг 4: Создание кода C

Создайте код C для входов переменного размера. По умолчанию 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. Щелкните ссылку Просмотр отчета.

  4. В списке созданных файлов щелкните 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 в генерируемых интерфейсах функций.

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

Связанные темы