Недавно я прочитал пост о переполнении стека о поиске целых чисел, которые являются идеальными квадратами.Поскольку я хотел поиграть с этим, я написал следующую маленькую программу:
PROGRAM PERFECT_SQUARE
IMPLICIT NONE
INTEGER*8 :: N, M, NTOT
LOGICAL :: IS_SQUARE
N=Z'D0B03602181'
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(N,15)
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
При компиляции с gfortran -O2
время выполнения составляет 4,437 секунды, с -O3 - 2,657 секунды.Затем я подумал, что компиляция с ifort -O2
могла бы быть быстрее, поскольку она могла бы иметь более быструю функцию SQRT
, но оказалось, что время выполнения теперь составляет 9,026 секунды, а с ifort -O3
то же самое.Я попытался проанализировать его с помощью Valgrind, и скомпилированная программа Intel действительно использует гораздо больше инструкций.
Мой вопрос: почему?Есть ли способ узнать, откуда именно разница?
РЕДАКТИРОВАТЬ:
- gfortran версии 4.6.2 и ifort версии 12.0.2
- разполучен при запуске
time ./a.out
и является реальным / пользовательским временем (sys всегда было почти 0) - это на Linux x86_64, и gfortran, и ifort являются 64-битными сборками
- ifort все встраивает, gfortran только при -O3, но последний ассемблерный код проще, чем у ifort, который много использует регистры xmm
- фиксированная строка кода, добавленная
NTOT=0
перед циклом, должна исправить проблему с другими версиями gfortran
Когда сложный оператор IF
удален, gfortran занимает примерно в 4 раза больше времени (10-11 секунд).Этого и следовало ожидать, так как в операторе приблизительно выбрасывается около 75% чисел, и на них не ставится SQRT
.С другой стороны, ifort использует только немного больше времени.Я предполагаю, что что-то идет не так, когда ifort пытается оптимизировать оператор IF
.
EDIT2:
Я пробовал с версией ifort 12.1.2.273 это намного быстрее, так что, похоже, они исправили это.