Fortran runtime warning: temporary array

2019-04-25 08:39发布

问题:

I get the fortran runtime warning "An array temporary was created" when running my code (compiled with gfortran) and I would like to know if there is a better way to solve this warning.

My original code is something like this:

allocate(flx_est(lsign,3))
allocate(flx_err(lsign,3))
do i=1,lsign
call combflx_calc(flx_est(i,:),flx_err(i,:))
enddo

Inside the subroutine I define the variables like this:

subroutine combflx_calc(flx_est,flx_err)
use,intrinsic              :: ISO_Fortran_env, only: real64
implicit none
real(real64),intent(inout) :: flx_est(3),flx_err(3)

flux_est and flx_err vectors may change inside the subroutine depending on several conditions and I need to update their values accordingly.

Fortran does not seem to like this structure. I can solve it defining temporary variables:

tmp_flx_est=flx_est(i,:)
tmp_flx_err=flx_err(i,:)
call combflx_calc(tmp_flx_est,tmp_flx_err)
flx_est(i,:)=tmp_flx_est
flx_err(i,:)=tmp_flx_err

But it seems to me quite a silly way to fix it.

As you may see I'm not an expert with Fortran, so any help is more than welcome.

回答1:

One way is to pass an assumed shape array

real(real64),intent(inout) :: flx_est(:),flx_err(:)

the other is to exchange the dimensions of your array, so that you can pass a contiguous section of the 2D array.

call combflx_calc(flx_est(:,i),flx_err(:,i))

The problem is that the explicit size dummy arguments of your procedure (var(n)) require contiguous arrays. The assumed shape arrays can have some stride.



回答2:

Your array temporary is being created because you are passing a strided array to your subroutine. Fortran arrays are column major so the leftmost index varies fastest in an array, or better said, the leftmost index is contiguous in memory and each variable to the right is strided over those to the left.

When you call

call combflx_calc(flx_est(i,:),flx_err(i,:))

These slices are arrays of your 3-vector strided by the length of lsign. The subroutine expects variables of a single dimension contiguous in memory, which the variable you pass into it is not. Thus, a temporary must be made for the subroutine to operate on and then copied back into your array slice.

Your "fix" does not change this, it just not longer warns about a temporary because you are using an explicitly created variable rather than the runtime doing it for you.

Vladimir's answer gives you options to avoid the temporary, so I will not duplicate them here.