I am using subroutines in Fortran 90 which have too arguments. On the first call of these subroutines the second one is useless but still present. I know that this is not a nice way to do things but for historical reasons it has been made like this.
For example:
CALL myroutine(A, B + C)
where:
SUBROUTINE myroutine (A, B)
IF(.NOT. first) THEN
!Using B in a way or another..
ELSE
!Other operations, not using B.
END IF
END SUBROUTINE routine
I am using gfortran 4.4.7 to compile with -O3.
I would like to know if the operation B + C, useless when it's the first call to myroutine because the second argument is unused, is performed or not...
Moreover, precise compiling optimizations are new to me, and I would be interested in knowing which resources I can refer to when facing such questions.
This isn't quite an answer to the question, more a comment on possibly optimizing the code.
As Floris & High Performance Mark comment, it is likely that the compiler still will execute B+C even if the subroutine does not use it. As an alternative to passing B+C to the subroutine every time, you could use the flag OPTIONAL for the variable B in the subroutine, combined with the PRESENT inquiry. You could then eliminate the B+C in the first call to the subroutine and then add it in for the second call:
PROGRAM main
IMPLICIT NONE
! definitions of a, b, c, etc
CALL myroutine(a)
CALL myroutine(a,b+c)
CONTAINS
SUBROUTINE myroutine(a,b)
<TYPE> :: a
<TYPE>, OPTIONAL :: b
IF(PRESENT(b)) THEN
! operations using b and a
ELSE
! operations using a only
ENDIF
END SUBROUTINE
END PROGRAM
Where <TYPE> is whatever type A and B are supposed to be.
Related
I have a Fortran program which uses a routine in a module to resize a matrix like:
module resizemod
contains
subroutine ResizeMatrix(A,newSize,lindx)
integer,dimension(:,:),intent(inout),pointer :: A
integer,intent(in) :: newSize(2)
integer,dimension(:,:),allocatable :: B
integer,optional,intent(in) :: lindx(2)
integer :: i,j
allocate(B(lbound(A,1):ubound(A,1),lbound(A,2):ubound(A,2)))
forall (i=lbound(A,1):ubound(A,1),j=lbound(A,2):ubound(A,2))
B(i,j)=A(i,j)
end forall
if (associated(A)) deallocate(A)
if (present(lindx)) then
allocate(A(lindx(1):lindx(1)+newSize(1)-1,lindx(2):lindx(2)+newSize(2)-1))
else
allocate(A(newSize(1),newSize(2)))
end if
do i=lbound(B,1),ubound(B,1)
do j=lbound(B,2), ubound(B,2)
A(i,j)=B(i,j)
end do
end do
deallocate(B)
end subroutine ResizeMatrix
end module resizemod
The main program looks like:
program resize
use :: resizemod
implicit none
integer,pointer :: mtest(:,:)
allocate(mtest(0:1,3))
mtest(0,:)=[1,2,3]
mtest(1,:)=[1,4,5]
call ResizeMatrix(mtest,[3,3],lindx=[0,1])
mtest(2,:)=0
print *,mtest(0,:)
print *,mtest(1,:)
print *,mtest(2,:)
end program resize
I use ifort 14.0 to compile the codes. The issue that I am facing is that sometimes I don't get the desired result:
1 0 0
1 0 5
0 0 -677609912
Actually I couldn't reproduce the issue (which is present in my original program) using the minimal test codes. But the point that I noticed was that when I remove the compiler option -fast, this problem disappears.
Then my question would be
If the pieces of code that I use are completely legal?
If any other method for resizing the matrices would be recommended which is better than the one presented in here?
The relevance of the described issue and the compiler option "-fast".
If I've read the code right it's legal but incorrect. In your example you've resized a 2x3 array into 3x3 but the routine ResizeMatrix doesn't do anything to set the values of the extra elements. The strange values you see, such as -677609912, are the interpretation, as integers. of whatever bits were lying around in memory when the memory location corresponding to the unset array element was read (so that it's value could be written out).
The relevance of -fast is that it is common for compilers in debug or low-optimisation modes, to zero-out memory locations but not to bother when higher optimisation is switched on. The program is legal in the sense that it contains no compiler-determinable syntax errors. But it is incorrect in the sense that reading a variable whose value has not been initialised or assigned is not something you regularly ought to do; doing so makes your program, essentially, non-deterministic.
As for your question 2, it raises the possibility that you are not familiar with the intrinsic functions reshape or (F2003) move_alloc. The latter is almost certainly what you want, the former may help too.
As an aside: these days I rarely use pointer on arrays, allocatable is much more useful and generally easier and safer too. But you may have requirements of which I wot not.
I have "inherited" a simple congruential pseudo-random-number generator that looks like this:
subroutine ribm(rndm,ial)
implicit none
integer :: ial
real :: rndm, al
ial=ial*65539
if(ial.lt.0) then
ial=ial+2147483647+1
endif
al=ial
rndm=al*0.4656613e-9
end subroutine ribm
The ial variable contains the RNG seed and it is initialised once outside the generator. The generator is supposed to produce pseudo-random numbers between 0 and 1, as usual. Therefore, ial must always stay non-negative. The code tries to enforce this condition using the if statement.
I test the generator using the following program:
program testribm
implicit none
real :: r
integer :: i
data i /12345/
call ribm(r,i)
call ribm(r,i)
call ribm(r,i)
call ribm(r,i)
call ribm(r,i)
call ribm(r,i)
print *,r,i
contains
subroutine ribm(rndm,ial)
! [...]
end subroutine ribm
end program testribm
If I compile with gfortran v4.8.2 with optimisation -O1 or lower, I get:
0.580895185 1247462939
OTOH, if I use -O2 I get:
-0.709615409 -1523887535
Note the negative seed value. Optimisation affects the integer arithmetics and the final result of the repeated calls to ribm.
I know how to work around/fix this problem. My question is: is this a gfortran bug? Or is this behaviour due to the fact that the code is non-standard? But if this is the case, shouldn't gfortran produce some warning message?
Optimization can change the actual calculations done. Don't be surprised if the results change for a non-standard calculation, such as one that involves integer overflow. My suggestion to implement algorithms in Fortran that use unsigned integers is to use the next-larger integer type. e.g., if the algorithm should be done with unsigned 32-bit integers, use Fortran's signed 64-bit integer.
I would add to M.S.B.'s answer, that the problem occurs only when the compiler optimizes several calls to ribm in one go. (My previous suggestion was invalid.)
But the answer to the original question. I don't think it's a compiler bug. 2147483647+1 is simply out of range. The question is why there is no warning even with -pedantic -Wall -Wextra. It turns out, pointed out by #Arek' Fu that one needs -Wstrict-overflow, whis is included only as -Wstrict-overflow=1 in -Wall.
Where possible, I recommend using functions iand, ior, ieor, ishft and similar for portable results, instead of arithmetic.
both answers are nice, as for a solution, I would think using parenthesis is the right way to go to prevent the compiler optimizing away?
subroutine ribm(rndm,ial)
implicit none
integer :: ial
real :: rndm, al
ial=ial*65539
if(ial.lt.0) then
ial=(ial+1)+2147483647
endif
al=ial
rndm=al*0.4656613e-9
end subroutine ribm
I have done a lot of work with array-based interpreted languages, but I'm having a look at Fortran. What has just occurred to me after writing my first bit of code is the question of whether or not gfortran will optimise an expression using array syntax by placing the expression in a single loop. In most array-based interpreters an expression such as A=B/n*2*pi (where B is an array) would require 5 loops and multiple array temporaries to evaluate. Is gfortran clever enough to optimise this out, and will my code below (the line that calculates the array from 0 to 2pi) be as efficient as an explicit do loop around the expression? Is there anything I should look out for when using array syntax if I'm worried about performance?
PROGRAM Sine
IMPLICIT NONE
REAL, PARAMETER :: PI = 3.415926535
INTEGER, PARAMETER :: z = 500
INTEGER :: ier
INTEGER, EXTERNAL :: PGBEG
REAL, DIMENSION(z) :: x,y
x=(indgen(z)-1.0)/z*(2*pi) ! This line...``
y=sin(x)
CALL plot(y,x)
CONTAINS
FUNCTION indgen(n) result(i)
INTEGER :: n
INTEGER, DIMENSION(n) :: i
INTEGER :: l
DO l=1,n
i(l)=l
END DO
END FUNCTION indgen
SUBROUTINE plot(y,x)
REAL, DIMENSION(:) :: x,y
ier=PGBEG(0,'/XWINDOW',1,1)
CALL PGENV(0.0,7.0,-1.0,1.0,0,1)
CALL PGLINE(SIZE(x),x,y)
CALL PGEND()
END SUBROUTINE plot
END PROGRAM Sine
In gfortran you can use the -Warray-temporaries flag to see all array temporaries generated. When I try your example no extra array temporary is generated (other than the one necessary to store the results of indgen(z)), so I guess gfortran is clever enough.
The expression z*(2*pi) is a compile-time constant, which the compiler can easily verify, so that should not be evaluated at run time regardless. Additionally, virtually all modern compilers should perform one-line "elemental" array operations within a single loop, and in many cases SIMD instructions will be generated (auto-vectorization).
Whether a temporary is generated usually depends on whether or not each element can be handled independently, and whether or not the compiler can prove this. Xiaolei Zhu's suggestion of using -Warray-temporaries is a good one. Don't mix this up wih -fcheck=array-temps, which I think only applies to temporaries generated for function calls.
Here's an example of such a message from gfortran:
foo.F90:4.12:
foo(1:20) = 2*foo(20:1:-1)
1
Warning: Creating array temporary at (1)
Your function call will be done in a separate loop, unless the compiler can inline it. Whether or not the compiler inlines a short function can be pretty unpredictable; it potentially depends on where that other function is defined, whether or not the function has the pure attribute (although in practice this rarely seems to matter), the vendor and version of the compiler itself, and the options you pass. Some compilers can generate a report for this; as I recall, the Intel compiler has a decent one.
Edit: It's also possible to inline the expression in this line pretty easily by hand, using an "implied do loop":
x = [ ( real(i)/z*(2*pi), i = 0, z-1) ]
Yes.
Fortran is compiled rather than interpreted.
It handles loops very well.
A small question on optimizing a program. The problem is stated as follows
Problem Statement:
The main code has a for/DO loop in which a subroutine is present. The subroutine need or need not be executed depending upon a flag I receive from user.
Obvious Solution:
Simplest way of doing it is using an IF loop to call the subroutine. But then this is time consuming if I have to check for the flag everytime the loop is executed. I am doing molecular dynamics and the number of times the loop will be executed will be of the order of 10^5 .
Qn: Is there a better way to do this, like I say to the program whether the subroutine has to be invoked depending on the flag once and for all? I am coding in Fortran 90. So it would be helpful if something can be said along that lines.
PROGRAM MAIN
IMPLICIT NONE
"ALL ARRAY INITIALIZATIONS
CALL DENSITY() ! I do a field based approach. So this is for grid formulation
DO i = 1, neq ! neq = number of eqbm cycles
CALL MC_CYC() ! Monte carlo steps
CALL DENSITY() ! Recalculate density
END DO
DO i = 1,nprod ! production cycle
DO j = 1, niter ! for averages of ensembles
CALL MC_CYC()
CALL DENSITY()
END DO
!do average here
IF(<flag is present>) ! This is where I needed to check flag. Because otherwise the flag will be checked everytime.
CALL RDF()
END IF
END DO
END PROGRAM MAIN
I am not sure that an IF statement is really going to slow down the program, even if called (more than) 100,000 times. You might only end up saving a second or two by restructuring the code (test this though!)
Anyway, if the flag is received at the start of the program, then you'd be able to write your code as
IF(<flag is present>) THEN
DO
...
CALL <subroutine name>
...
ENDDO
ELSE
DO
...
ENDDO
ENDIF
where the second DO loop omits the subroutine CALL.
EDIT
As another alternative (that might be cheaper to implement) is to pre-process the data and have the flag keyed in at compile-time. This might make the user a bit annoyed to have to recompile the program when changing the flag, but it'd make your job easier.
Anyway, you'd have something like
DO
...
#ifdef <flag>
CALL <subroutine name>
#endif
ENDDO
I'm trying to incorporate error checking within a pure procedure I am writing. I would like something like:
pure real function func1(output_unit,a)
implicit none
integer :: a, output_unit
if (a < 0) then
write(output_unit,*) 'Error in function func1: argument must be a nonnegative integer. It is ', a
else
func1 = a/3
endif
return
end function func1
However, pure functions are not allowed to have IO statements to external files, so I tried passing a unit number to the function, e.g. output_unit = 6, which is the default output. gfortran still regards this as illegal. Is there a way around this? Is it possible to make the function a derived type (instead of intrinsic type real here) which outputs a string when there is an error?
You are not the first person to have this problem, and I'm happy to say that this flaw in the standard will be remedied in Fortran 2015. As stated in this document (page 6, header "Approved changes to the standard"), "the restriction on the appearance of an error stop statement in a pure procedure should be removed".
The Fortran 2008 standard included the error stop statement in the context of some new parallel computing features. It signals an error and makes all processes stop as soon as is practicable. Currently, neither stop nor error stop statements are allowed in pure procedures, because they're obviously not thread-safe. In practice this is unnecessarily restrictive in cases where an internal error occurs.
Depending on your compiler, you may have to wait patiently for the implementation. I know that Intel has implemented it in their ifort compiler. ("F2015: Lift restriction on STOP and ERROR STOP in PURE/ELEMENTAL procedures")
alternative
For an alternative approach, you could have a look at this question, though in you case this is probably slightly trickier as you have to change the do concurrent keyword, not just pure.
(end of proper answer)
if getting dirty hands is an option ...
In the meantime you could do something brutal like
pure subroutine internal_error(error_msg)
! Try hard to produce a runtime error, regardless of compiler flags.
! This is useful in pure subprograms where you want to produce an error,
! preferably with a traceback.
!
! Though far from pretty, this solution contains all the ugliness in this
! single subprogram.
!
! TODO: replace with ERROR STOP when supported by compiler
implicit none
character(*), intent(in) :: error_msg
integer, dimension(:), allocatable :: molested
allocate(molested(2))
allocate(molested(2))
molested(3) = molested(4)
molested(1) = -10
molested(2) = sqrt(real(molested(1)))
deallocate(molested)
deallocate(molested)
molested(3) = molested(-10)
end subroutine internal_error
Should anyone ask, you didn't get this from me.
I've found an answer myself, detailed here. It uses what is considered "obsolescent", but still does the trick; it is called alternate return. Write the procedure as a subroutine as it doesn't work on functions.
pure real subroutine procA(arg1)
implicit none
integer :: arg1
if (arg < 0) then
return 1 ! exit the function and go to the first label supplied
! when function was called. Also return 2, 3 etc.
else
procA = ... ! whatever it should do under normal circumstances
endif
endsubroutine procA
....
! later on, procedure is called
num = procA(a, *220)
220 write(6,*) 'Error with func1: you've probably supplied a negative argument'
What would probably be better is what eriktous suggested--get the procedure to return a status, perhaps as a logical value or an integer, and get the program to check this value every time after it calls the procedure. If all's well, carry on. Otherwise, print a relevant error message.
Comments welcome.