在fortran中为纯函数生成数组临时值



我的问题是关于gfortran(gcc版本8.1.0(gcc))在处理临时数组时的一些令人费解的行为。下面的代码是用-O3 -Warray-temporaries编译的。

考虑以下构造矩阵直积和的可能性:

program Pexam1
use Maux, only: kron
double precision:: A(3, 3), B(3, 3)
double precision:: C(5, 5), D(5, 5)
double precision:: rAC(15, 15), rBD(15, 15), r1(15, 15), r2(15, 15)

r1 = -kron(3, A, 5, C) - kron(3, B, 5, D)
!                             1
! Warning: Creating array temporary at (1)
rAC = -kron(3, A, 5, C)
!           1
! Warning: Creating array temporary at (1)   
r2 = rAC - kron(3, B, 5, D)
end program Pexam1

有两个警告,但我不希望出现第二个警告(在rAC = -kron(3, A, 5, C)中)为什么简单地在第一行r1 = -kron(3, A, 5, C) - kron(3, B, 5, D)中,相同的第一部分被评估在没有临时数组的情况下非常好。这种不一致的原因是什么?为了避免不必要地创建临时数组,应该记住什么?

模块Maux如下

module Maux
contains
pure function kron(nA, A, nB, B) result (C)
! // direct product of matrices 
integer, intent(in)         :: nA, nB
double precision, intent(in)  :: A(nA, nA), B(nB, nB)
double precision              :: C(nA*nB, nA*nB)
integer :: iA, jA, iB, jB
forall (iA=1:nA, jA=1:nA, iB=1:nB, jB=1:nB)&
C(iA + (iB-1) * nA, jA + (jB-1) * nA) = A(iA, jA) * B(iB, jB)
end function kron
end module Maux

如果您构建此程序,您会注意到只有在使用减号评估kron时才会创建临时数组:


program Pexam1
use Maux, only: kron
double precision:: A(3, 3), B(3, 3)
double precision:: C(5, 5), D(5, 5)
double precision:: rAC(15, 15), rBD(15, 15), r1(15, 15), r2(15, 15)

rAC = kron(3, A, 5, C) ! no temporary
r2  = -kron(3, B, 5, D) ! temporary
end program Pexam1

不要忘记,fortran(=)中的每个assignment都是一个独立的运算,而不是等号的r.h.s。因此,当kron为负时,编译器需要:

  1. 评估kron(3,B,5,D),将其放在临时中(我们称之为tmp)
  2. 评估-tmp
  3. 将此临时操作的结果(可以具有任何类型/种类)分配给r2

显然,gFortran已经足够好了,当您有步骤1时。仅(正赋值),运算结果直接复制到rAC,而没有任何临时性(我想是因为rAC与调用kron的结果具有相同的秩、类型和形状)。

最新更新