Forrtl: warning (402): fort: (1)

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 each subprogram / record statement call.

Subroutine call:

 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 write operator:

  write(91,*)'Gerade: ',gerade(maxloc(reslt(1:i)),minsumloc,1), & gerade(maxloc(reslt(1:i)),minsumloc,2) 

The stripe array 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, this is not a problem in terms of accuracy, but it can slow down the program, so most of the writing to RAM is performed. So, how much does this slow down my calculations ( stripe can have a size around stripe(100,300,3) and may become bigger sometime later)? And how can I avoid such extra arrays ?.

+4
source share
1 answer

I think you get this warning because subroutines are passed in non-contiguous segments of the array, and the compiler decided that the subroutine should receive an adjacent temporary array containing the necessary values. I expect the routine code to be written in terms of an array and implicitly assumes that we always execute 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) 

means (as if)

 stripe(j,1,1) stripe(j,2,1) stripe(j,3,1) ... 

Since, as I expect, you know Fortran arrays are stored with the fastest first index value, your section of the array goes through memory.

You can suppress the warning using the noarg_temp_created compiler noarg_temp_created . Note that this only suppresses the warning (which can save the program runtime smidgeon, I suppose), it does not affect what the compiler does, temporary arrays will be created anyway.

You can write code to create temporary arrays containing the section that must be passed to the subroutine. I do not see much advantage in this; I expect the compiler to release code that surpasses any code you write for such a simple operation.

Or you can change / move your original array once before starting to call the subprogram and give it the correct shape and location for slicing into adjacent blocks. And then unpermute / unreshape at the end of all calls.

The only convincing way to answer your question about the relative performance of your current code and any alternative formulations is to encode them and pull out your stopwatch.

+6
source

Source: https://habr.com/ru/post/1496738/


All Articles