Будут ли компиляторы gfortran или ifort разумно использовать инструкции SIMD при суммировании произведения двух массивов?

StackOverflow https://stackoverflow.com//questions/21050913

Вопрос

У меня есть код, написанный с помощью numpy, и я подумываю о его портировании на Фортран для повышения производительности.

Одна операция, которую я делаю несколько раз, — это суммирование поэлементного произведения двух массивов:

sum(A*B)

Похоже, в этом помогут объединенные инструкции умножения-сложения.Мой нынешний процессор не поддерживает эти инструкции, поэтому я пока не могу что-то протестировать.Однако я могу перейти на новый процессор, поддерживающий FMA3 (процессор Intel Haswell).

Кто-нибудь знает, будет ли достаточно компиляции программы с "-march=native" (или эквивалентом ifort), чтобы компилятор (gfortran или ifort) разумно использовал инструкции SIMD для оптимизации этого кода, или вы думаете, что я это сделаю? придется возиться с компиляторами или кодом?

Это было полезно?

Решение 3

Благодаря совету Сяолея Чжу я теперь знаю, что gfortran будет использовать объединенное умножение-сложение для оптимизации. sum(A*B).Например, с помощью этого кода:

Программный тест неявный

реальный, размерность(7) ::а, б

а = (/2,0, 3,0, 5,0, 7,0, 11,0, 13,0, 17,0/)

б = (/4,0, 6,0, 8,0, 10,0, 12,0, 14,0, 16,0/)

напечатать *, сумма(а*б)
конечная программа

Я могу скомпилировать его с помощью f95 sum.f95 -o sum -O3 -march=core-avx2, и objdump -d sum | grep vfmadd дисплеи

40088б:c4 e2 71 99 44 24 30 vfmadd132ss 0x30(%rsp),%xmm1,%xmm0

400892:c4 e2 69 b9 44 24 34 vfmadd231ss 0x34(%rsp),%xmm2,%xmm0

400899:c4 e2 61 b9 44 24 38 vfmadd231ss 0x38(%rsp),%xmm3,%xmm0

4008а0:c4 e2 59 b9 44 24 3c vfmadd231ss 0x3c(%rsp),%xmm4,%xmm0

4008a7:c4 e2 51 b9 44 24 40 vfmadd231ss 0x40(%rsp),%xmm5,%xmm0

4008ае:c4 e2 49 b9 44 24 44 vfmadd231ss 0x44(%rsp),%xmm6,%xmm0

4008b5:c4 e2 41 b9 44 24 48 vfmadd231ss 0x48(%rsp),%xmm7,%xmm0

Итак, gfortran развернул цикл и вставил 7 объединенных инструкций умножения-сложения.Если я создаю более крупные, случайные, многомерные массивы, я все равно вижу всплывающее окно vfmadd231ss один раз (поэтому он не разворачивает цикл).

Другие советы

Если вы используете -march=native на машине с SIMD компилятор должен генерировать инструкции SIMD, хотя я всегда использовал -xHost отметьте вместо этого ifort.

Но я не совсем уверен, как заставить их сделать это "с умом".У меня такое чувство, что в -O3 level ifort и gfortran, как правило, чрезмерно агрессивны в отношении векторизации (то есть они используют функциональность SIMD чаще, чем следовало бы).Очень часто мне приходится отключать векторизацию, чтобы получить наиболее эффективный код.Это, конечно, может быть правдой, а может и не быть правдой для вас.

Обычно лучше использовать векторные библиотеки, оптимизированные для этой задачи.Вы можете использовать vdmul в МКЛ или gsl_vector_mul в GSL для этого есть.

Используя -march=NEWARCH в результате будет создан код, настроенный для новой архитектуры, но не может быть запущен на более ранней архитектуре.Вы можете использовать -mtune=NEWARCH отметьте, где NEWARCH - это архитектура вашего нового процессора.Это сгенерирует код, настроенный для новой архитектуры, но все еще исполняемый на старой.Поскольку у вас еще нет новой машины, -mtune вероятно, это то, что вам нужно в данный момент.

С помощью ifort вы можете использовать флаги отчета о векторизации, чтобы показать, какая часть программы была векторизована.Например, ifort Отметить -vec-report=1 мы предоставим вам такую информацию во время компиляции.Я уверен, что в gfortran найдется эквивалентный флаг.

версии gfortran, где sum(a*b) дал лучшую векторизацию, чем dot_product(a,b) давно устарели.Код, который вы показываете, использует последовательные инструкции AVX2 fma.

В реализации dot_product без косвенной индексации или других осложнений (сам по себе простой цикл) fma, вероятно, будет медленнее, чем комбинация инструкций параллельного умножения и сложения simd, поскольку умножение может быть выполнено вне критического пути задержки.gfortran использование параллельного simd fma для dot_product может быть весьма эффективным в более сложных случаях.

Вам понадобится либо -O2 -ftree-vectorize -ffast-math -march=native or -O3 -ffast-math -march=native (а также подходящие длины векторов) для векторизации, и gfortran может не выполнить векторизацию внутри параллельной области OpenMP.

В gfortran 4.9, похоже, удалена опция -ftree-vectorizer-verbose.-fdump-tree-vect записывает детали проходов векторизации в файл .vect с разными именами, выбранными для разных основных версий gcc.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top