Да. Иногда я могу делать такие глупости, что через секунду я не могу понять, как это возможно ... Я ошибочно полагал, что генераторы случайных чисел имели примерно одинаковую производительность, но это, очевидно, не так. Я написал с нуля на обоих языках действительно простой конгруэнтный генератор, идентичный (просто перевод), ничего не использованный в контексте serius (и на самом деле «физические» результаты просто мусор), но я получаю те же результаты с точностью машины в C и в Fortran, но код на Fortran выполняется примерно на 25% быстрее. Я чувствую себя лучше. Еще раз спасибо.

исал (для моего класса по численным методам теоретической физики) очень простую программу для случайного блуждания в измерении 2. Вот оно:

program random_walk

implicit none

integer, parameter :: Nwalker = 1000000
integer, parameter :: Nstep   = 100
integer, parameter :: Nmeas   = 10

integer :: posx, posy, move

integer :: is, im, iw
real    :: start_time, stop_time

double precision, dimension(Nmeas) :: dist, r2
real :: rnd

do im = 1, Nmeas
    dist(im) = im*Nstep
    r2(im)   = 0.0
end do

call cpu_time(start_time)
do iw = 1, Nwalker
    posx = 0
    posy = 0
    do im = 1, Nmeas
        do is = 1, Nstep
            call random_number(rnd)
            move = 4*rnd
            if (move == 0) posx = posx + 1
            if (move == 1) posy = posy + 1
            if (move == 2) posx = posx - 1
            if (move == 3) posy = posy - 1
        end do
        r2(im) = r2(im) + posx**2 + posy**2
    end do
end do
r2 = r2 / Nwalker
call cpu_time(stop_time)
do im = 1, Nmeas
    print '(f8.6, "   ", f8.6)', log(dist(im)), log(r2(im))
end do
print '("Time = ", f6.3, " seconds")', stop_time - start_time
end program

В конце должно быть напечатано 10 строк и 2 столбца: первый столбец - логарифм «времени» (количество шагов), второй столбец - логарифм среднего квадрата расстояния от начала координат. Второй столбец «в среднем» должен быть равен первому. Пока все хорошо, программа работает хорошо, результаты очень разумные. Но здесь проблема; на моем macbookpro (2,7 ГГц Intel Core i7, компилятор gfortran 7.1.0, оптимизация -O2) он работает в среднем более 20 секунд для запуска. Но если я закомментирую эти строки:

! do im = 1, Nmeas
!    print '(f8.6, "   ", f8.6)', log(dist(im)), log(r2(im))
! end do

которые находятся за пределами вычисления "stop_time", в результате время выполнения составляет ... менее 6 секунд !?

Как это возможно?

Ответы на вопрос(1)

Решение Вопроса

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

Чтобы проверить это, вы можете добавить-fdump-tree-optimized флаг, чтобы получить специальную исходную форму под названием GIMPLE, и вы можете сравнить выходные данные для этих двух вариантов исходного кода. Он записывает вывод в файл с именемyourfilename.f90.something.optimized, Я действительно могу видеть, что большая часть отсутствует. В основном весьr2 массив и операции с ним оптимизированы. Вы также можете сравнить сгенерированную сборку, если знаете это лучше.

 ulrich01 дек. 2017 г., 01:06
Это довольно урок для меня, спасибо. Тем временем я переписал программу на C (очень просто, просто глупый построчный перевод оригинальной программы), и время выполнения составляет около 6,8 секунд с распечаткой результата или без него. Означает ли это, что C перевыполняет Fortran в 3 раза по времени для такой простой вычислительной задачи? Это действительно кажется мне сюрпризом.
 Vladimir F01 дек. 2017 г., 08:52
Обычно это не так. Но без кода никто не может сказать. Вы можете создать новый вопрос об этом, но вам придется предоставить много деталей. Оба кода, результаты измерений, попробуйте использовать один и тот же генератор случайных чисел или нет случайных чисел ...
 ulrich01 дек. 2017 г., 13:49
Да. Иногда я могу делать такие глупости, что через секунду я не могу понять, как это возможно ... Я ошибочно полагал, что генераторы случайных чисел имели примерно одинаковую производительность, но это, очевидно, не так. Я написал с нуля на обоих языках действительно простой конгруэнтный генератор, идентичный (просто перевод), ничего не использованный в контексте serius (и на самом деле «физические» результаты просто мусор), но я получаю те же результаты с точностью машины в C и в Fortran, но код на Fortran выполняется примерно на 25% быстрее. Я чувствую себя лучше. Еще раз спасибо.

Ваш ответ на вопрос