问题
i get the following warning at runtime:
...
forrtl: warning (402): fort: (1): In call to I/O Write routine, an array temporary was created for argument #2
forrtl: warning (402): fort: (1): In call to I/O Write routine, an array temporary was created for argument #3
forrtl: warning (402): fort: (1): In call to GERADHEIT_LINIAL, an array temporary was created for argument #2
forrtl: warning (402): fort: (1): In call to GERADHEIT_LINIAL, an array temporary was created for argument #3
...
for every call of the subroutine / write statement.
The call of the subroutine:
integer :: l,kreise
character(*)::setname
real(8),diemnsion(:,:,:),allocatable::stripe
integer,dimension(:)s(j)
...code and allocation of arrays...
do j=n(1)
call geradheit_linial (s(j),stripe(j,1:s(j),1),
& stripe(j,1:s(j),2),setname)
end do
...
subroutine geradheit_linial (ndaten,x,r,setname)
implicit none
integer,intent(in) :: ndaten
real(8),dimension(ndaten),intent(in) :: x,r
character(*),intent(in) :: setname
and the write statement:
write(91,*)'Gerade: ',gerade(maxloc(reslt(1:i)),minsumloc,1),
& gerade(maxloc(reslt(1:i)),minsumloc,2)
The array stripe
is allocated with the maximum value expected for each dimension, so most of the time only a subset is passed through the call.
As far as i understand, it isn't really a problem in terms of accuracy but may slow down the program, hence a lot of writing to the RAM is done. So how much does it slow down my computation (stripe
may have a dimension of about stripe(100,300,3)
and could get bigger sometime later)? And how can i avoid such extra arrays?.
回答1:
I think that you are getting this warning because the subroutines are being passed non-contiguous array sections and the compiler has decided that the subroutine should get a contiguous temporary array containing the necessary values. I expect that the subroutine code is written in terms of an array and implicitly assumes, as we always do when programming in Fortran, that it is contiguous.
If I read your code correctly the compiler understands this statement
stripe(j,1:s(j),1)
to mean (as it were)
stripe(j,1,1)
stripe(j,2,1)
stripe(j,3,1)
...
Since, as I expect that you are aware, Fortran arrays are stored with the first index value changing most rapidly, your array section strides through memory.
You could suppress the warning with the compiler option noarg_temp_created
. Note that this does only suppress the warning (which might save a smidgeon of the program's run time I suppose), it does not affect what the compiler does, the temporary arrays will still be created.
You could write code to create temporary arrays containing the section to be passed to the subroutine. I don't see much advantage in doing this; I'd expect the compiler to issue code that outperforms any code you write for such a straightforward operation.
Or you could reshape / permute your original array once, before starting to call the subroutine, and give it the right shape and arrangement for slicing into contiguous blocks. And then unpermute / unreshape at the end of all the calls.
The only conclusive way to answer your question about the relative performance of your current code and any alternative formulations is to code them up and get out your stopwatch.
来源:https://stackoverflow.com/questions/18204249/forrtl-warning-402-fort-1