【发布时间】:2021-06-12 13:22:27
【问题描述】:
我有这个我最初实现的代码的 sn-p 需要检查。检查后,我现在想知道它是否可以优化。特别是提出的问题是:
“预先初始化该大型计算的所有单个成员而不是直接在其中计算它们会更好吗(即 sqrt() )?”
换句话说,在计算本身执行计算时,内存分配与 CPU 时间之间是否存在权衡?
这里是代码 sn-p(编辑):
do id=1,3
BF(idx1,idx2,idx3) = BF(idx1,idx2,idx3) +&
! i-j, i-k
2*bsa_wind_coeff(ilib,4+id,inode)*bsa_wind_coeff(jlib,1+id,jnode)*bsa_wind_coeff(klib,1+id,knode)* &
(nodCorr(id,p1)* sqrt(SU(i1,id,inode)*SU(i1,id,jnode))) * (nodCorr(id,p2)* sqrt(SU(i2,id,inode)*SU(i2,id,knode)) )+&
! i-j, j-k
2*bsa_wind_coeff(ilib,1+id,inode)*bsa_wind_coeff(jlib,4+id,jnode)*bsa_wind_coeff(klib,1+id,knode)* &
(nodCorr(id,p1)* sqrt(SU12(id,inode)*SU12(id,jnode))) * (nodCorr(id,p3)* sqrt(SU(i2,id,jnode)*SU(i2,id,knode)) )+&
! i-k, j-k
2*bsa_wind_coeff(ilib,1+id,inode)*bsa_wind_coeff(jlib,1+id,jnode)*bsa_wind_coeff(klib,4+id,knode)* &
(nodCorr(id,p2)* sqrt(SU12(id,inode)*SU12(id,knode))) * (nodCorr(id,p3)* sqrt(SU(i1,id,jnode)*SU(i1,id,knode)) )
enddo
! dir 1-2
BF(idx1,idx2,idx3) = BF(idx1,idx2,idx3) +&
! i-k, i-j
bsa_wind_coeff(ilib,8,inode)*bsa_wind_coeff(jlib,3,jnode)*bsa_wind_coeff(klib,2,knode)* &
(nodCorr(1,p2)* sqrt( SU(i2,1,inode)*SU(i2,1,knode) )) * (nodCorr(2,p1)* sqrt( SU(i1,2,inode)*SU(i1,2,jnode) ) )+&
! i-j, j-k
bsa_wind_coeff(ilib,2,inode)*bsa_wind_coeff(jlib,8,jnode)*bsa_wind_coeff(klib,3,knode)* &
(nodCorr(1,p2)* sqrt( SU12(1,inode)*SU12(1,jnode) )) * (nodCorr(2,p3)* sqrt( SU(i2,2,jnode)*SU(i2,2,knode) ) )+&
! j-k, i-k
bsa_wind_coeff(ilib,3,inode)*bsa_wind_coeff(jlib,2,jnode)*bsa_wind_coeff(klib,8,knode)* &
(nodCorr(1,p3)* sqrt( SU(i1,1,jnode)*SU(i1,1,knode) )) * (nodCorr(2,p2)* sqrt( SU12(2,inode)*SU12(2,knode) ) )+&
! i-j, i-k
bsa_wind_coeff(ilib,8,inode)*bsa_wind_coeff(jlib,2,jnode)*bsa_wind_coeff(klib,3,knode)* &
(nodCorr(1,p1)* sqrt( SU(i1,1,inode)*SU(i1,1,jnode) )) * (nodCorr(2,p2)* sqrt( SU(i2,2,inode)*SU(i2,2,knode) ) )+&
! j-k, i-j
bsa_wind_coeff(ilib,3,inode)*bsa_wind_coeff(jlib,8,jnode)*bsa_wind_coeff(klib,2,knode)* &
(nodCorr(1,p3)* sqrt( SU(i2,1,jnode)*SU(i2,1,knode) )) * (nodCorr(2,p1)* sqrt( SU12(2,inode)*SU12(2,jnode) ) )+&
! i-k, j-k
bsa_wind_coeff(ilib,2,inode)*bsa_wind_coeff(jlib,3,jnode)*bsa_wind_coeff(klib,8,knode)* &
(nodCorr(1,p2)* sqrt( SU12(1,inode)*SU12(1,knode) )) * (nodCorr(2,p3)* sqrt( SU(i1,2,jnode)*SU(i1,2,knode) ) )
! dir 1-3
BF(idx1,idx2,idx3) = BF(idx1,idx2,idx3) +&
! i-k, i-j
bsa_wind_coeff(ilib,9,inode)*bsa_wind_coeff(jlib,4,jnode)*bsa_wind_coeff(klib,2,knode)* &
(nodCorr(1,p2)* sqrt( SU(i2,1,inode)*SU(i2,1,knode) )) * (nodCorr(3,p1)* sqrt( SU(i1,3,inode)*SU(i1,3,jnode) ) )+&
! i-j, j-k
bsa_wind_coeff(ilib,2,inode)*bsa_wind_coeff(jlib,9,jnode)*bsa_wind_coeff(klib,4,knode)* &
(nodCorr(1,p2)* sqrt( SU12(1,inode)*SU12(1,jnode) )) * (nodCorr(3,p3)* sqrt( SU(i2,3,jnode)*SU(i2,3,knode) ) )+&
! j-k, i-k
bsa_wind_coeff(ilib,4,inode)*bsa_wind_coeff(jlib,2,jnode)*bsa_wind_coeff(klib,9,knode)* &
(nodCorr(1,p3)* sqrt( SU(i1,1,jnode)*SU(i1,1,knode) )) * (nodCorr(3,p2)* sqrt( SU12(3,inode)*SU12(3,knode) ) )+&
! i-j, i-k
bsa_wind_coeff(ilib,9,inode)*bsa_wind_coeff(jlib,2,jnode)*bsa_wind_coeff(klib,4,knode)* &
(nodCorr(1,p1)* sqrt( SU(i1,1,inode)*SU(i1,1,jnode) )) * (nodCorr(3,p2)* sqrt( SU(i2,3,inode)*SU(i2,3,knode) ) )+&
! j-k, i-j
bsa_wind_coeff(ilib,4,inode)*bsa_wind_coeff(jlib,9,jnode)*bsa_wind_coeff(klib,2,knode)* &
(nodCorr(1,p3)* sqrt( SU(i2,1,jnode)*SU(i2,1,knode) )) * (nodCorr(3,p1)* sqrt( SU12(3,inode)*SU12(3,jnode) ) )+&
! i-k, j-k
bsa_wind_coeff(ilib,2,inode)*bsa_wind_coeff(jlib,4,jnode)*bsa_wind_coeff(klib,9,knode)* &
(nodCorr(1,p2)* sqrt( SU12(1,inode)*SU12(1,knode) )) * (nodCorr(3,p3)* sqrt( SU(i1,3,jnode)*SU(i1,3,knode) ) )
! dir 2-3
BF(idx1,idx2,idx3) = BF(idx1,idx2,idx3) +&
bsa_wind_coeff(ilib,10,inode)*bsa_wind_coeff(jlib,4,jnode)*bsa_wind_coeff(klib,3,knode)* &
(nodCorr(2,p2)* sqrt( SU(i2,2,inode)*SU(i2,2,knode) )) * (nodCorr(3,p1)* sqrt( SU(i1,3,inode)*SU(i1,3,jnode) ) )+&
bsa_wind_coeff(ilib,3,inode)*bsa_wind_coeff(jlib,10,jnode)*bsa_wind_coeff(klib,4,knode)* &
(nodCorr(2,p2)* sqrt( SU12(2,inode)*SU12(2,jnode) )) * (nodCorr(3,p3)* sqrt( SU(i2,3,jnode)*SU(i2,3,knode) ) )+&
bsa_wind_coeff(ilib,4,inode)*bsa_wind_coeff(jlib,3,jnode)*bsa_wind_coeff(klib,10,knode)* &
(nodCorr(2,p3)* sqrt( SU(i1,2,jnode)*SU(i1,2,knode) )) * (nodCorr(3,p2)* sqrt( SU12(3,inode)*SU12(3,knode) ) )+&
bsa_wind_coeff(ilib,10,inode)*bsa_wind_coeff(jlib,3,jnode)*bsa_wind_coeff(klib,4,knode)* &
(nodCorr(2,p1)* sqrt( SU(i1,2,inode)*SU(i1,2,jnode) )) * (nodCorr(3,p2)* sqrt( SU(i2,3,inode)*SU(i2,3,knode) ) )+&
bsa_wind_coeff(ilib,4,inode)*bsa_wind_coeff(jlib,10,jnode)*bsa_wind_coeff(klib,3,knode)* &
(nodCorr(2,p3)* sqrt( SU(i2,2,jnode)*SU(i2,2,knode) )) * (nodCorr(3,p1)* sqrt( SU12(3,inode)*SU12(3,jnode) ) )+&
bsa_wind_coeff(ilib,3,inode)*bsa_wind_coeff(jlib,4,jnode)*bsa_wind_coeff(klib,10,knode)* &
(nodCorr(2,p2)* sqrt( SU12(2,inode)*SU12(2,knode) )) * (nodCorr(3,p3)* sqrt( SU(i1,3,jnode)*SU(i1,3,knode) ) )
一些注意事项:
bsa_wind_coeffs 是一个公共变量(在模块中声明),而代码 sn-p 中存在的所有其他变量都是直接传递的(即我假设在本地创建一个副本)。在过程本身内,索引 ilib、jlib、klib、inode、jnode、knode 是循环的。在外部过程中多次调用此计算。
编辑: 这里的所有变量都是static,因为它们被计算一次(在调用此过程之前),然后只是根据一些索引值进行遍历,如您所见。也就是说,在每次调用时,都会传递相同的数组。
【问题讨论】:
-
如果没有最小的完整示例,很难说清楚,重要的是循环(引导索引)以及有关变量大小、数据类型等的一些信息。
-
@albert,循环(当然在可能的情况下)已经优化为按列进行。数据类型(在操作本身中)始终为 real(8 个字节)。大小可能会有所不同,但我会说这并不能解决问题。我的问题想要更“conceptual”,也就是说,如果存在一个阈值,在这个阈值之前这个实现可能是首选的 w.r.t。相反(预先初始化 tmp vars 中的所有成员)。
-
sqrt计算非常昂贵,因此将结果存储在临时数组中可能很有用,但这完全取决于使用相同输入数组的调用次数,其中sqrt被采用,所需额外内存的大小,将部分保存在内部缓存中的可能性.... -
基本上我同意 Albert 的观点——没有一个最小但完整的例子,除了看起来像模板应用外,很难说很多,所以我会尽量减少网格上每个点的工作尽可能在内循环之外进行计算,尤其是 sqrts。但是哎呀,这段代码伤害了我的眼睛!我要做的第一件事就是把它分解成一些更简单的陈述,而不是一个巨大的、单一的、令人困惑的东西。
-
@veryreverie 我不是浮点计算方面的专家,但是当假设 sqrt 的项很小时,可能会发生 a*b 小于适合浮点的项number 并且给出 0 是 NaN 或 .. 所以 sqrt 也给出了一个数字。首先计算 sqrt(a)*sqrt(b) 并将给出“合理”的数字,以及 sqrt 的乘积。另请注意,最好使用(也可能在原始版本中)绝对值,或者保证 a 和 b 为正。所有这些可能都超出了这里的范围。
标签: performance optimization memory-management fortran