Сгенерируйте код SIMD для функций MATLAB

Вы можете сгенерировать код SIMD (одна инструкция, несколько данных) из некоторых функций MATLAB с помощью технологий Intel AVX и Intel SSE. SIMD является вычислительной парадигмой, в которой одна команда обрабатывает несколько данных. Во многих современных процессорах есть SIMD-инструкции, которые, например, выполняют сразу несколько сложений или умножений. Для интенсивных в вычислительном отношении операций между поддерживаемыми функциями SIMD-компоненты могут значительно улучшить эффективность сгенерированного кода на платформах Intel.

Функции MATLAB, которые Поддержка SIMD Кода

При выполнении определенных обстоятельств можно сгенерировать код SIMD с помощью технологии Intel SE или Intel AVX. В следующей таблице перечислены функции MATLAB, которые поддерживают генерацию кода SIMD. В таблице также указаны условия, при которых предоставляется поддержка.

Функция MATLABУсловия
plus
  • Для Intel AVX и Intel SSE входной сигнал имеет тип данных single, double, int8, int16, int32 или int64.

  • Для Intel AVX-512 входной сигнал имеет тип данных single или double.

minus
  • Для Intel AVX и Intel SSE входной сигнал имеет тип данных single, double, int8, int16, int32 или int64.

  • Для Intel AVX-512 входной сигнал имеет тип данных single или double.

times
  • Для Intel AVX и Intel SSE входной сигнал имеет тип данных single, double, int16, или int32.

  • Для Intel AVX-512 входной сигнал имеет тип данных single или double.

rdivideВходной сигнал имеет тип данных single или double.
sqrtВходной сигнал имеет тип данных single или double.
ceil
  • Для Intel SSE и Intel AVX входной сигнал имеет тип данных single или double.

  • AVX-512 Intel не поддерживается.

floor
  • Для Intel SSE и Intel AVX входной сигнал имеет тип данных single или double.

  • AVX-512 Intel не поддерживается.

max

Входной сигнал имеет тип данных single или double.

min

Входной сигнал имеет тип данных single или double.

Если у вас есть DSP System Toolbox™, можно сгенерировать код из определенных объектов MATLAB System. Для получения дополнительной информации смотрите Системные объекты в DSP System Toolbox, которые Поддержка генерацию кода SIMD (DSP System Toolbox).

Сгенерируйте код SIMD в зависимости от простого кода С

Рассмотрим функцию MATLAB dynamic. Эта функция состоит из операций сложения и умножения между массивами переменного размера A и B. Эти массивы имеют тип данных single и верхняя граница 100 x 100.

function C = dynamic(A, B)
   assert(all(size(A) <= [100 100]));
   assert(all(size(B) <= [100 100]));
   assert(isa(A, 'single'));
   assert(isa(B, 'single'));

   C = zeros(size(A), 'like', A);
   for i = 1:numel(A)
       C(i) = (A(i) .* B(i)) + (A(i) .* B(i));
   end
end

Чтобы сгенерировать простой код С в командной строке:

  1. Для C генерация кода библиотеки, создание coder.config объект

    cfg = coder.config('lib');
  2. Чтобы сгенерировать статическую библиотеку в расположении по умолчанию, codegen\lib\dynamic, использовать codegen функция t.

    codegen('-config', cfg, 'dynamic');

  3. В списке сгенерированных файлов нажмите dynamic.c. В простом (не-SIMD) коде С каждая итерация цикла выдает один результат.

    void dynamic(const float A_data[], const int A_size[2], const float B_data[],
                 const int B_size[2], float C_data[], int C_size[2])
    {
      float C_data_tmp;
      int i;
      int loop_ub;
      (void)B_size;
      C_size[0] = (signed char)A_size[0];
      C_size[1] = (signed char)A_size[1];
      loop_ub = (signed char)A_size[0] * (signed char)A_size[1];
      if (0 <= loop_ub - 1) {
        memset(&C_data[0], 0, loop_ub * sizeof(float));
      }
      loop_ub = A_size[0] * A_size[1];
      for (i = 0; i < loop_ub; i++) {
        C_data_tmp = A_data[i] * B_data[i];
        C_data[i] = C_data_tmp + C_data_tmp;
      }
    }

Чтобы сгенерировать C SIMD код в командной строке:

  1. Для C генерация кода библиотеки, используйте coder.config функция для создания coder.CodeConfig объект.

    cfg = coder.config('lib');
  2. Установите coder.HardwareImplementation TargetHWDeviceType объекта свойство к 'Intel->x86-64 (Linux 64)' или 'Intel->x86-64 (Windows64)'.

    cfg.HardwareImplementation.TargetHWDeviceType = 'Intel->x86-64 (Windows64)';

  3. Установите coder.HardwareImplementation ProdHWDeviceType объекта свойство к 'Intel->x86-64 (Linux 64)' или 'Intel->x86-64 (Windows64)'

    cfg.HardwareImplementation.TargetHWDeviceType = 'Intel->x86-64 (Windows64)';

    Если вы используете приложение MATLAB Coder для генерации кода:

    • Установите параметр Hardware Device равным None-Select device below.

    • Установите параметр Device vendor равным Intel или AMD.

    • Установите Device type равным Intel->x86-64 (Linux 64) или Intel->x86-64 (Windows64).

  4. Установите CodeReplacementLibrary свойство библиотеки Intel AVX или Intel SSE. Этот пример использует Intel SSE для Windows.

    cfg.CodeReplacementLibrary = 'Intel SSE (Windows)';
    

    Библиотека, которую вы выбираете, зависит от того, какое расширение набора команд поддерживает ваш процессор.

    Для получения дополнительной информации см. https://www.intel.com/content/www/us/en/support/articles/000005779/processors.html. В этой таблице перечислены входные инструкции Intel для каждой библиотеки замещения кода.

    Библиотека замещения кодаНабор внутренних инструкций Intel
    Intel SSEМРЗ, SSE2, SSE4.1
    Intel AVXSSE, SSE2, SSE4.1, AVX, AVX2
    Функции Intel AVX-512SSE, SSE2, SSE4.1, AVX, AVX2, AVX-512

    Если вы используете приложение MATLAB Coder для генерации кода, на вкладке Custom Code установите параметр Code replacement library в библиотеку Intel SSE или Intel AVX.

  5. Используйте codegen функция для генерации статической библиотеки в расположении по умолчанию, codegen\lib\dynamic.

    codegen('-config', cfg, 'dyanamic');
    
  6. В списке сгенерированных файлов нажмите dynamic.c.

    void dynamic(const float A_data[], const int A_size[2], const float B_data[],
                 const int B_size[2], float C_data[], int C_size[2])
    {
      __m128 r;
      float C_data_tmp;
      int i;
      int loop_ub;
      int scalarLB;
      int vectorUB;
      (void)B_size;
      C_size[0] = (signed char)A_size[0];
      C_size[1] = (signed char)A_size[1];
      loop_ub = (signed char)A_size[0] * (signed char)A_size[1];
      if (0 <= loop_ub - 1) {
        memset(&C_data[0], 0, loop_ub * sizeof(float));
      }
      loop_ub = A_size[0] * A_size[1];
      scalarLB = (loop_ub / 4) << 2;
      vectorUB = scalarLB - 4;
      for (i = 0; i <= vectorUB; i += 4) {
        r = _mm_mul_ps(_mm_loadu_ps(&A_data[i]), _mm_loadu_ps(&B_data[i]));
        _mm_storeu_ps(&C_data[i], _mm_add_ps(r, r));
      }
      for (i = scalarLB; i < loop_ub; i++) {
        C_data_tmp = A_data[i] * B_data[i];
        C_data[i] = C_data_tmp + C_data_tmp;
      }
    }

    Инструкции SIMD являются внутренними функциями, которые начинаются с идентификатора _mm. Эти функции обрабатывают несколько данных в одной итерации цикла, потому что цикл увеличивается на четыре для single типы данных. Для double типы данных, цикл увеличивается на два. Для кода MATLAB, который обрабатывает больше данных и является более в вычислительном отношении интенсивным, чем код в этом примере, наличие команд SIMD может значительно ускорить время выполнения кода.

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

Список внутренних функций Intel для поддерживаемых функций MATLAB см. в разделе https://software.intel.com/sites/landingpage/IntrinsicsGuide/.

Ограничения

Сгенерированный код не содержит SIMD код, когда код MATLAB соответствует следующим условиям:

  • Скалярные операции вне цикла. Для примера, если a,b, и c являются скалярами, сгенерированный код не содержит SIMD-код для такой операции, как c=a+b.

  • Косвенно индексированные массивы или матрицы. Для примера, если A,B,C, и D являются векторами, сгенерированный код не содержит SIMD-код для такой операции, как D(A)=C(A)+B(A).

  • Параллельные контуры для (parfor). The parfor цикл не содержит кода SIMD, но петли в теле parfor цикл может содержать код SIMD.

Похожие темы