Ускорьте код для данных Переменного Размера

Данные переменного размера являются данными, размер которых может измениться во время выполнения. Поддержки 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 не может определить или вычислить верхнюю границуЗадайте верхнюю границу.Смотрите задают верхние границы для массивов Переменного Размера (Simulink) и диагностирование и фиксация ошибок несоответствия размера.
    MATLAB пытается вычислить верхнюю границу для неограниченных данных переменного размера.Если данные неограниченны, включите динамическое выделение памяти. Смотрите динамическое выделение памяти управления
  6. Сгенерируйте код C/C++ с помощью функции fiaccel.

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

О функции MATLAB uniquetol

Этот пример использует функциональный 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 будет использоваться (чтение). Например:

    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. Создайте входные параметры правильного класса, сложности и размера, чтобы передать MATLAB uniquetol и 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 значительно ускоряет осуществление алгоритма фиксированной точки.