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

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

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

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

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

    cfg = coder.mexconfig;

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

    cfg.EnableVariableSizing = false;

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

    fiaccel -config cfg foo
    

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

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

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

    mexcfg = coder.mexconfig;

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

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

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

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

    fiaccel -config mexcfg foo
    

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

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

  1. В РЕДАКТОРА MATLAB добавьте директиву компиляции %#codegen в верхней части вашей функции.

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

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

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

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

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

  3. Сгенерируйте MEX-функцию используя fiaccel. Используйте следующие опции командной строки:

    • -args {coder.typeof...} если у вас есть входы переменного размера

    • -report чтобы сгенерировать отчет генерации кода

    Для примера:

    fiaccel -report foo -args {coder.typeof(0,[2 4],1)}
    
    Эта команда использует coder.typeof чтобы задать один вход переменного размера для функции foo. Первый аргумент, 0, указывает тип входных данных (double) и сложности (real). Второй аргумент, [2 4], указывает размер, матрица с двумя размерностями. Третий аргумент, 1, указывает, что вход имеет переменный размер. Верхняя граница равна 2 для первой размерности и 4 для второго измерения.

    Примечание

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

  4. Исправьте ошибки несоответствия размера:

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

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

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

Об униккетоле функции MATLAB

Этот пример использует функцию uniquetol. Эта функция возвращается в векторном B версию входа вектора A, где элементы являются уникальными для в пределах допуска tol друг о друге. В векторных B, abs(B(i) - B(j))> tol для всех i и j. Первоначально предположим, что входной вектор A может хранить до 100 элементов.

function B = uniquetol(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 = uniquetol(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, используйте fiaccel функция.

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

    T = numerictype(1, 16, 15);
    fiaccel -report uniquetol -args {coder.typeof(fi(0,T),[1 100],1),coder.typeof(fi(0,T))}
    

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

    Выполнение этой команды генерирует ошибку компилятора:

    ??? Size mismatch (size [1 x 1] ~= size [1 x 2]).
    The size to the left is the size 
    of the left-hand side of the assignment.
    
  2. Откройте отчет об ошибке и выберите вкладку Variables.

Ошибка указывает на несоответствие размера между левой и правой сторонами оператора назначения B = [B A(i)];. Назначение B = A(1) устанавливает размер B как скаляр фиксированного размера (1 x 1). Поэтому конкатенация [B A(i)] создает вектор 1 x 2.

Шаг 4: Исправьте ошибку несоответствия размера

Чтобы исправить эту ошибку, объявите B быть вектором переменного размера.

  1. Добавьте этот оператор к uniquetol функция:

    coder.varsize('B');

    Оно должно появиться перед B используется (read). Для примера:

    function B = uniquetol(A, tol) %#codegen
    A = sort(A);
    
    coder.varsize('B');
    
    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

    Функция coder.varsize объявляет каждый образец B в uniquetol для переменного размера.

  2. Сгенерируйте код снова с помощью той же команды:

    fiaccel -report uniquetol -args {coder.typeof(fi(0,T),[1 100],1),coder.typeof(fi(0,T))}

    В текущей папке, fiaccel генерирует MEX-функцию для uniquetol именованные uniquetol_mex и предоставляет ссылку на отчет генерации кода.

  3. Щелкните ссылку Просмотреть отчет.

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

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

Шаг 5: Сравните скорость выполнения MEX-функции с оригинальным кодом

Запустите исходный алгоритм MATLAB и MEX-функцию с одинаковыми входами для того же количества итераций цикла и сравните их скорости выполнения.

  1. Создайте входы правильного класса, сложности и размера, чтобы перейти к uniquetol MATLAB и MEX-функции.

    x = fi(rand(1,90), T);
    tol = fi(0, T);
    
  2. Запуск исходного uniquetol функция в цикле и время, сколько времени требуется для выполнения 10 итераций цикла.

    tic; for k=1:10, b = uniquetol(x,tol); end; tSim=toc
    
  3. Запустите сгенерированную MEX-функцию с теми же входами для того же количества итераций цикла.

    tic; for k=1:10, b = uniquetol_mex(x,tol); end; tSim_mex=toc
    
  4. Сравните времена выполнения.

    r = tSim/tSim_mex
    

    Этот пример показывает, что генерация MEX-функции с помощью fiaccel значительно ускоряет выполнение алгоритма с фиксированной точкой.