Внутренний dot_product медленнее, чем a * a + b * b + c * c? - PullRequest
0 голосов
/ 30 мая 2018

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

  program test

  real*8 , dimension(3) :: idmat
  real*8 :: dummy(3)

  idmat=0
  dummy=0

  do i=1,3

      idmat(i)=1

  enddo

  do j=1,10**10

  !   dummy(mod(j,3)+1)=dot_product(idmat,idmat)
      dummy(mod(j,3)+1)=idmat(1)*idmat(1)+idmat(2)*idmat(2)+idmat(3)*idmat(3)

  enddo

  print*, dummy

  end program test

Вот что меня смущает:

1.Нет -O3 Оптимизация

Если я использую: gfortran test.f90 -o test ; time ./test

Я нахожу время выполнения 6 297 с с использованием функции dot_product (прокомментировано выше) и 4486 с использованием явного написания руководства.Как это имеет смысл?

2.Включая оптимизацию -O3

Если я использую: gfortran test.f90 -O3 -o test ; time ./test

, я нахожу время выполнения 1808 с и 1803 с соответственно.Так что на самом деле оба имеют одинаковую скорость.

3.На самом деле я ожидаю, что

... - это встроенная функция, которая будет быстрее, поскольку она может:

  1. вычислять 3 продукта параллельно
  2. добавить 3 продукта

, где явная форма должна последовательно:

  1. вычислить продукт 1
  2. вычислить продукт 2
  3. вычислить продукт 3
  4. добавить 3 продукта

Нужно ли создавать новую параллельную функцию dot_product , чтобы быть быстрее?Или есть дополнительная опция для компилятора gfortran, которую я не знаю?

Обратите внимание: я читаю в интернете о SIMD, авто-векторизации и распараллеливании в современном Fortran.Хотя я кое-что узнал, на мой вопрос нигде не было ответа.

1 Ответ

0 голосов
/ 30 мая 2018

Нет смысла даже смотреть на неоптимизированные числа.Оптимизированные числа одинаковы, поэтому все в порядке.

"... это встроенная функция, которая должна быть быстрее, поскольку она может: вычислять 3 продукта параллельно"

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

Ну, по крайней мере для обычного смысла параллельный с использованием потоков или аналогичных,Параллельно можно использовать векторные инструкции и запланировать наложение инструкций в конвейере ЦП.Это может сделать оптимизирующий компилятор и, вероятно, будет сделано для обеих версий, когда вы используете -O3.Не следует ожидать, что это произойдет, если оптимизация не включена.

Использование «параллельных» инструкций ( SIMD ) иногда может быть улучшено с помощью директив компилятора, таких как !$omp simd или !$DEC VECTOR.

«Нужно ли создавать новую параллельную функцию dot_product, чтобы быть быстрее?»

Да, обычно так и есть.Например, используя OpenMP.Или вы можете:

"Или есть дополнительная опция для компилятора gfortran, которую я не знаю?"

Да, автоматическое распараллеливание https://gcc.gnu.org/wiki/AutoParInGCC, например -floop-parallelize-all -ftree-parallelize-loops=4

Обратите внимание, что он не будет выполнять эти отдельные умножения параллельно, он сделает параллельный цикл i.

...