exponenta event banner

Создание кода SIMD для функций MATLAB

С помощью технологий Intel AVX и Intel SSE можно генерировать код SIMD (одна команда, несколько данных) из определенных функций MATLAB. 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.

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

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

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

max

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

min

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

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

Создать код SIMD в сравнении с простым кодом C

Рассмотрим функцию 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

Чтобы создать простой код C в командной строке:

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

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

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

  3. В списке созданных файлов щелкните dynamic.c. В простом (не SIMD) коде 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])
    {
      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;
      }
    }

Создание SIMD C код в командной строке:

  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.

    • Задайте для параметра поставщика устройства значение Intel или AMD.

    • Установите тип устройства в значение 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
    AVX-512 IntelSSE, SSE2, SSE4.1, AVX, AVX2, AVX-512

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

  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 цикл, содержащий код SIMD, должен быть разделен на четыре для отдельных типов данных. Второй цикл обрабатывает оставшуюся часть данных.

Список встроенных функций 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). parfor цикл не содержит SIMD-код, но цикл в теле parfor цикл может содержать код SIMD.

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