Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
27430 Discussions

Getting double the number of calls I expect to a function

ur
Novice
664 Views

This program should call sorti(3f) ten times, but calls it twenty. It calls it ten times for gfortran(1) and nvfortran(1).  ifort version 2021.3.0.

 

 

program main
! bug: ifort calls sorti(1) twice for each invocation
implicit none
character(len=*),parameter :: x='(*(g0,1x))'
call doboth( [100,100,500,300,100,400,500,200] )
call doboth( [0,0,0,0,0] )
call doboth( [100,500,300,400,200] )
call doboth( [100,500,-300,0,400,200] )
call doboth( [600,300,200,100,0,-100,-200,-300] )
write(*,x)repeat('=',80)
contains
subroutine doboth(ints)
integer :: ints(:)
integer,allocatable :: iii(:)
iii=ints
write(*,x)repeat('=',80)
write(*,x)'INPUT',iii
iii(sorti(iii))=iii
write(*,x)'LHS ',iii
iii=iii(sorti(iii))
write(*,x)'RHS ',iii
end subroutine doboth
function sorti(ints) result(counts)
integer :: ints(:)
integer :: counts(size(ints)), i
integer, save :: calls=0
! WARNING: this sort is slow as mollasses, but if fun to write in one line
! relative sort first take account of duplicates
counts=[(count(ints(i) > ints) + count(ints(i) == ints(:i)), i=1,size(ints) )]
calls=calls+1
write(*,x)'CALLS',CALLS,'VALUES',counts
end function sorti
end program

0 Kudos
1 Solution
Devorah_H_Intel
Moderator
471 Views

Thank you for your report. I have escalated this to compiler engineering for further investigation. 

View solution in original post

7 Replies
Steve_Lionel
Black Belt Retired Employee
650 Views

That is...weird. I can reproduce it, but I don't understand it. 

ur
Novice
633 Views

Weird enough I played with it a long time before posting, but I am finally convinced it is real. Since it could affect performance significantly and answers (with a procedure with side-effects ) I posted it even though I had a nagging feeling I might be missing a typo for a long time. Wanted some feedback before looking at the machine code which I am rusty at, but I ran this several times just mumbling exactly that ... weird, weird, weird. Good to know it reproduced and isn't a glitch in my machine.

ur
Novice
631 Views

Am I somehow accidently creating threads?

ur
Novice
625 Views

program main
integer :: iii(5)
iii=[100,200,300,400,500]
iii(sorti(iii))=iii
contains
function sorti(ints) result(counts)
integer :: ints(:)
integer :: counts(size(ints))
integer, save :: calls=0
counts=[5,4,3,2,1]
calls=calls+1
write(*,'(*(g0,1x))')'CALLS',CALLS
end function sorti
end program

 

Did not get is smaller before.  This reproduces it; but if ints(:) is changed to ints(5) or size(ints) is changed to 5 it vanishes.

 

Steve_Lionel
Black Belt Retired Employee
608 Views

No, it is not creating threads. My guess is that it has to do with the use of the sorti function on the left side of the assignment. It seems the compiler feels it has to call the function twice as part of determining the array of indexes used in the assignment. It isn't allowed to do this.

ur
Novice
594 Views

Very artificial test, but works fine with sorti on RHS. Made the test a little more dramatic so it actually causes an error

so a little easier to test with if more verbose

 

 

program main
integer :: iii(5)
iii=[100,200,300,400,500]
iii(sorti(iii))=iii
! iii=iii(sorti(iii)) ! works fine
if(all([500,400,300,200,100]/=iii))stop '<ERROR> values not in expected order'
stop '<INFO> all is well'
contains
function sorti(ints) result(counts)
integer :: ints(:)
integer :: counts(size(ints))
integer, save :: calls=0
counts=[5,4,3,2,1]
! intentionally cause overindexing error if calls.ne.0
counts=counts+calls
calls=calls+1
write(*,'(*(g0,1x))')'CALLS',CALLS
end function sorti
end program

Devorah_H_Intel
Moderator
472 Views

Thank you for your report. I have escalated this to compiler engineering for further investigation. 

Reply