оптимизация ifort и gfortran и сравнение времени выполнения

Я прочитал этот пост Непонятная разница в производительности между ifort и gfortran с 2012 года по попытался запустить код самостоятельно:

PROGRAM PERFECT_SQUARE
IMPLICIT NONE
INTEGER*8 :: N, M, NTOT
LOGICAL :: IS_SQUARE

N=4
WRITE(*,*) IS_SQUARE(N)

NTOT = 0
DO N = 1, 1000000000
    IF (IS_SQUARE(N)) THEN
        NTOT = NTOT + 1
    END IF
END DO
WRITE (*, *) NTOT ! should find 31622 squares
END PROGRAM

LOGICAL FUNCTION IS_SQUARE(N)
IMPLICIT NONE
INTEGER*8 :: N, M

! check if negative
IF (N .LT. 0) THEN
    IS_SQUARE = .FALSE.
    RETURN
END IF

! check if ending 4 bits belong to (0,1,4,9)
M = IAND(int(N, kind(8)), int(15, kind(8)))
IF (.NOT. (M .EQ. 0 .OR. M .EQ. 1 .OR. M .EQ. 4 .OR. M .EQ. 9)) THEN
    IS_SQUARE = .FALSE.
    RETURN
END IF

! try to find the nearest integer to sqrt(n)
M = DINT(SQRT(DBLE(N)))
IF (M**2 .NE. N) THEN
    IS_SQUARE = .FALSE.
    RETURN
END IF

IS_SQUARE = .TRUE.
RETURN
END FUNCTION

(Я изменил несколько строк, чтобы код скомпилировался).

Я скомпилировал с помощью ifort 19.1.3.304 и gfortran 10.2.0.

Исполняемый файл ifort работал намного быстрее, чем gfortran, и включал гораздо больше команд. Судя по сообщению, ifort 12.1.2.273 должен был решить проблему, но, похоже, она не исправлена.

Если я отключу векторизацию на ifort, я получу гораздо лучшие результаты на ifort, но все равно хуже, чем на gfortran.

Если я удалю строки:

N=4
WRITE(*,*) IS_SQUARE(N)

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

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

Я скомпилировал с -O3 на обоих и попытался добавить -no-vec к ifort. Я открыт для других флагов компиляции.

ОБНОВИТЬ:

ifort example.f90 -O3 -o example_ifort

gfortran example.f90 -O3 -o example_gnu

время выполнения для example_ifort составляет 3 секунды, а для example_gnu — 1 секунду.


person nadavhalahmi    schedule 09.03.2021    source источник
comment
Не имеет отношения к вашей проблеме, но что вы имеете в виду под int(N, kind(8))? Я думаю, вы имеете в виду kind=8 или kind(m). Написание int(n,kind(8)) — это очень странный способ написания int(n) с точно таким же значением.   -  person francescalus    schedule 09.03.2021
comment
работал намного быстрее, включал намного больше команд, стал намного хуже, на самом деле это не так уж много значит. Какие именно параметры командной строки используются с каждым компилятором?   -  person steve    schedule 09.03.2021
comment
francescalus: я сделал то, что было скомпилировано для меня... это всего лишь пример кода. steve: я перепробовал много вариантов, но давайте сначала обсудим простые:   -  person nadavhalahmi    schedule 10.03.2021