forrtl: warning (402): fort: (1)

匿名 (未验证) 提交于 2019-12-03 01:38:01

问题:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!