Возможно ли группирование одинаковых функций с помощью инструкции SIMD? - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть сценарий, что многие точно такие же функции (для простоты, давайте просто рассмотрим здесь C / C ++ и python) будут одновременно выполняться на моей машине.Интуитивно я просто использую многопоточность для обработки каждого экземпляра функции как потока для использования параллизма, они не борются за одни и те же ресурсы, но будут выполнять много операций ветвления (например, для цикла).Однако, поскольку они на самом деле являются одинаковыми функциями, я думаю о пакетировании их с использованием некоторых SIMD-инструкций, например AVX-512.Конечно, оно должно быть автоматическим, чтобы пользователям не приходилось изменять свой код.

Причина?Поскольку каждый поток / процесс / контейнер / ВМ занимает ресурсы, но AVX требуется только одна инструкция.Таким образом, я могу удерживать большее количество пользователей с одним и тем же оборудованием.

Большинство статей, которые я нахожу в Интернете, посвящены использованию инструкций AVX внутри функции, например, для ускорения обработки потоковых данных или для выполнения больших вычислений.Никто из них не упоминает о пакетировании разных экземпляров одной и той же функции.

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

Вот мои вопросы

  1. Сложно (или возможно) автоматически преобразовать обычную функцию в пакетную версию?
  2. Если 1 - нет, какие ограничения я должен наложить на функцию, чтобы сделать это возможным?Например, если функция имеет только один путь независимо от данных?
  3. Существуют ли другие технологии для более эффективного решения проблемы?Я не думаю, что GPU - это хороший вариант для меня, потому что GPU не поддерживает IO или инструкции ветвления, хотя его SIMT идеально подходит для моей цели.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Существует два способа исправить это: векторизация (SIMD) и распараллеливание (потоки).

GCC может уже выполнять векторизацию SIMD, которую вы хотите, при условии, что функция встроена, а типы и операции совместимы (и он автоматически встроит мелкие функции без вашего запроса).

Например,

inline void func (int i) {
   somearray[i] = someotherarray[i] * athirdarray[i];
}

for (int i = 0; i < ABIGNUMBER; i++)
   func (i);

Векторизация и встраивание включены при -O3.

Если функциислишком сложный, и / или GCC еще не векторизует его, тогда вы можете использовать OpenMP или OpenACC для его распараллеливания.

OpenMP использует специальную разметку, чтобы сообщить компилятору, где порождать потоки.

Например,

#pragma omp parallel
#pragma omp for
for (int i = 0; i < ABIGNUMBER; i++)
    ....

И да, вы можете делать это и на GPU!Вам нужно немного больше печатать, чтобы правильно копировать и копировать данные.На GPU работают только размеченные области.Все остальное работает на CPU, поэтому ввод / вывод и т. Д. Не является проблемой.

#pragma omp target map(somearray,someotherarray,athirdarray)
#pragma omp parallel
#pragma omp for
for (int i = 0; i < ABIGNUMBER; i++)
    ....

OpenACC - аналогичная идея, но более специализированная для графических процессоров.

Вы можете найти OpenMP иКомпиляторы OpenACC во многих местах.И GCC, и LLVM поддерживают графические процессоры NVidia.LLVM имеет некоторую поддержку графических процессоров AMD, а также доступны неофициальные сборки GCC (с официальной поддержкой в ​​ближайшее время).

0 голосов
/ 21 сентября 2018

SSE / AVX - это в основном векторная единица, она позволяет выполнять простые операции (например, + - * / и, или, XOR и т. Д.) Над массивами из нескольких элементов одновременно.AVX1 и 2 имеют 256-байтовые регистры, так что вы можете сделать, например, 8 32-битных синглов одновременно или 4 двойных.AVX-512 идет, но довольно редко.

Так что, если все ваши функции - это операции над массивами базовых типов, это естественное соответствие.Переписать вашу функцию с помощью встроенных функций AVX можно, если операции очень просты.Сложные вещи (например, не совпадающие по ширине вектора) или даже выполнение в ассемблере - это сложная задача.

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

...