Подтвердить что ты не робот

Параллельно для vs omp simd: когда использовать каждый?

OpenMP 4.0 представляет новую конструкцию под названием "omp simd". Какая польза от использования этой конструкции над старой "параллельной для"? Когда каждый будет лучшим выбором по сравнению с другим?

EDIT: Вот интересная бумага, связанная с директивой SIMD.

4b9b3361

Ответ 1

Связанный стандарт относительно прозрачен (p 13, строки 19 + 20)

Когда какой-либо поток встречает конструкцию simd, итерации цикл, связанный с конструкцией, может быть выполнен по SIMD-дорожкам которые доступны для потока.

SIMD - это суб-нить. Чтобы сделать его более конкретным, на процессоре вы могли бы представить с помощью директив SIMD, чтобы конкретно запросить векторизация фрагментов итераций цикла, которые индивидуально принадлежат одному и тому же потоку. Он разоблачает несколько уровней parallelism, которые существуют в одном многоядерном процессоре, независимо от платформы. См. Например, дискуссию (наряду с материалами ускорителя) в этом сообщении блога Intel.

В принципе, вы захотите использовать omp parallel для распространения работы на разные потоки, которые затем могут переноситься на несколько ядер; и вы захотите использовать omp simd, чтобы использовать векторные конвейеры (скажем) в каждом ядре. Обычно omp parallel будет идти "снаружи", чтобы иметь дело с более грубым параллельным распределением работы, а omp simd будет обходить тесные петли внутри этого, чтобы использовать мелкозернистый parallelism.

Ответ 2

Простой ответ:

OpenMP используется только для использования нескольких потоков для нескольких ядер. Это новое расширение simd позволяет явно использовать команды SIMD для современных процессоров, таких как Intel AVX/SSE и ARM NEON.

(Обратите внимание, что инструкция SIMD выполняется в одном потоке и в одном ядре по дизайну. Однако значение SIMD может быть довольно расширено для GPGPU. Но, я думаю, вам не нужно рассматривать GPGPU для OpenMP 4.0.)

Итак, как только вы узнаете инструкции SIMD, вы можете использовать эту новую конструкцию.


В современном процессоре примерно три типа parallelism: (1) уровень команд parallelism (ILP), (2) уровень уровня parallelism (TLP) и (3) инструкции SIMD (мы могли бы сказать, что это векторный уровень или так).

ILP выполняется автоматически вашими внекорпоративными процессорами или компиляторами. Вы можете использовать TLP, используя OpenMP parallel for и другие библиотеки потоков. Итак, как насчет SIMD? Способы их использования (а также автоматическая векторизация компиляторов). OpenMP simd - это новый способ использования SIMD.

Возьмем очень простой пример:

for (int i = 0; i < N; ++i)
  A[i] = B[i] + C[i];

Приведенный выше код вычисляет сумму двух N-мерных векторов. Как вы можете легко видеть, в массиве A[] нет (завитой от цикла) зависимости данных. Этот цикл неловко параллелен.

Возможно, существует несколько способов распараллеливать этот цикл. Например, до OpenMP 4.0 это можно распараллелить, используя только конструкцию parallel for. Каждый поток будет выполнять итерации N/#thread на нескольких ядрах.

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

Использование SIMD будет выглядеть так:

for (int i = 0; i < N/8; ++i)
  VECTOR_ADD(A + i, B + i, C + i);

В этом коде предполагается, что (1) инструкция SIMD (VECTOR_ADD) - это 256-битная или 8-позиционная (8 * 32 бит); и (2) N кратно 8.

8-позиционная SIMD-команда означает, что 8 элементов в векторе могут выполняться в одной машинной инструкции. Обратите внимание, что новейший AVX от Intel предоставляет такие 8-позиционные (32-разрядные * 8 = 256 бит) векторные инструкции.

В SIMD вы по-прежнему используете одно ядро ​​(опять же, это только для обычных процессоров, а не для графических процессоров). Но вы можете использовать скрытый parallelism в оборудовании. Современные процессоры выделяют аппаратные ресурсы для инструкций SIMD, где каждая SIMD-полоса может выполняться параллельно.

Вы можете использовать нить-уровень parallelism одновременно. Вышеприведенный пример может быть далее распараллелен parallel for.

(Тем не менее, я сомневаюсь, сколько циклов может быть действительно преобразовано в циклы SIMDized. Спецификация OpenMP 4.0 кажется немного неясной в этом смысле. Таким образом, реальная производительность и практические ограничения будут зависеть от реализаций реальных компиляторов.)


Подводя итог, конструкция simd позволяет использовать инструкции SIMD, в свою очередь, можно использовать более parallelism вместе с уровнем уровня parallelism. Тем не менее, я думаю, что фактические реализации будут иметь значение.

Ответ 3

Компиляторы не обязаны упрощать оптимизацию simd в параллельной области при наличии предложения simd. Компиляторы Я знаком с продолжением поддержки вложенных циклов, параллельных внешних, векторных внутренних, так же, как и раньше.
Раньше обычно применялись директивы OpenMP для предотвращения оптимизаций переключения циклов, связанных с внешним параллельным циклом (несколько циклов с клаузулой). Кажется, это изменилось в нескольких компиляторах. OpenMP 4 открывает новые возможности, в том числе оптимизацию параллельного внешнего контура с не-векционируемым внутренним циклом, посредством своего рода разработки полосы, когда omp parallel делает [для] simd. ifort иногда сообщает об этом в качестве векторизации внешнего цикла, когда это делается без предложения simd. Затем он может быть оптимизирован для меньшего количества потоков, чем omp parallel do simd, для которого, похоже, требуется больше потоков, чем ширина вектора simd, чтобы окупиться. Такое различие может быть выведено, так как без предложения simd компилятор неявно просят оптимизировать число циклов, например 100 или 300, в то время как предложение simd запрашивает безусловную оптимизацию simd. gcc 4.9 omp parallel для simd выглядел довольно эффективно, когда у меня была 24-ядерная платформа.