我的问题是关于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
为负时,编译器需要:
- 评估
kron(3,B,5,D)
,将其放在临时中(我们称之为tmp
) - 评估
-tmp
- 将此临时操作的结果(可以具有任何类型/种类)分配给
r2
显然,gFortran已经足够好了,当您有步骤1时。仅(正赋值),运算结果直接复制到rAC
,而没有任何临时性(我想是因为rAC
与调用kron
的结果具有相同的秩、类型和形状)。