Фортран: 10 вложенных циклов медленные с завершением оператора печати
У меня есть некоторый код, который запускается примерно за секунду, но после очень незначительного редактирования замедляется.
Следующий код выполняется через 1 секунду с gfortran -O3
program loop
implicit none
integer n, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10
parameter(n=18) !<=== most important
integer i,array(n)
real cal
real p1(n)
do i=1,n
p1(i)=float(i)/10.
enddo
write (*,1) p1
1 format (10(f6.2))
cal=0.
i1=0
i2=0
do i1=1,n
!write(*,1) cal !<-- too slow if write here
do i2=1,n
do i3=1,n
do i4=1,n
do i5=1,n
do i6=1,n
do i7=1,n
do i8=1,n
do i9=1,n
do i10=1,n
cal=p1(i1) !<-- perfectly happy to compute, as long as I don't write
array(i1)=i1+i2
enddo
enddo
enddo
enddo
enddo
enddo
enddo
enddo
enddo
!write(*,1) cal !<-- and too slow if write here too!
enddo
write(*,*) (array(i),i=1,n)
stop
end
Прежде всего, прости меня за смесь f77 и 90. Это пример, основанный на реальной проблеме. Однако существенным моментом является то, что если параметр n = 17, все в порядке. Второе-последнее оператор записи может быть некомментирован, и код выполняется примерно за секунду. Тем не менее, при n=18 код замедляется... если, если оператор записи со второго по последний закомментирован, он выполняется за секунду с n=18.
В двух тестах всего 17^10 и 18^10 итераций. Я не смог найти никаких указаний на ограничение количества итераций. Я продолжаю думать, что 18^10 должно превышать некоторый предел, но я не знаю, что. И почему утверждение print имеет значение для n=18, а не для n = 17? Больше информации: использование Mem близко к нулю. Процессор i5-4570, процессор с тактовой частотой 3,20 ГГц.
Если я использую -O0, код всегда работает очень медленно.
1 ответ
С gfortan 4.8.3 я не вижу большой разницы во времени выполнения write
заявления и опуская их, но есть огромная разница между -O3
а также -O0
, Причина этого в том, что компилятор может массово оптимизировать циклы с -O3
с которым это не связано -O0
, Компилятор может по существу выработать ответ заранее и полностью пропустить циклы. При более высоких оптимизациях компилятор также может использовать более сложные функции вашего ЦП, которые работают быстрее.
Ввод write
Операторы внутри цикла несколько нарушают способность компилятора агрессивно оптимизировать циклы, а это означает, что он больше не может полностью их пропускать, что приводит к более медленным временам выполнения, которые вы видите. Вероятно, вы используете старую версию gfortran, которая не очень хорошо справляется с этой ситуацией.