exponenta event banner

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

Данные переменного размера - это данные, размер которых может измениться во время выполнения. MATLAB ® поддерживает ограниченные и неограниченные данные переменного размера для создания кода. Ограниченные данные переменного размера имеют фиксированные верхние границы. Эти данные могут распределяться статически в стеке или динамически в куче. Неограниченные данные переменного размера не имеют фиксированных верхних границ. Эти данные должны быть распределены в куче. По умолчанию для генерации кода 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, расширяющей вектор в цикле

Сведения о uniquetol функции 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. Откройте отчет об ошибках и перейдите на вкладку Переменные.

Ошибка указывает на несоответствие размеров левой и правой сторон оператора назначения 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. В отчете о создании кода выберите закладку Переменные.

    Размер переменной 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 значительно ускоряет выполнение алгоритма с фиксированной точкой.