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

Getting double the number of calls I expect to a function

ur
新分销商 II
2,102 次查看

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 项奖励
1 解答
Devorah_H_Intel
主持人
1,336 次查看

The fix is in just released oneAPI 2023.1.0

 

在原帖中查看解决方案

0 项奖励
8 回复数
Steve_Lionel
名誉分销商 III
2,088 次查看

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

0 项奖励
ur
新分销商 II
2,071 次查看

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.

0 项奖励
ur
新分销商 II
2,069 次查看

Am I somehow accidently creating threads?

0 项奖励
ur
新分销商 II
2,063 次查看

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.

 

0 项奖励
Steve_Lionel
名誉分销商 III
2,046 次查看

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.

0 项奖励
ur
新分销商 II
2,032 次查看

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

0 项奖励
Devorah_H_Intel
主持人
1,909 次查看

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

Devorah_H_Intel
主持人
1,337 次查看

The fix is in just released oneAPI 2023.1.0

 

0 项奖励
回复