优化乘以零

时间:2017-02-02 11:56:20

标签: optimization fortran gfortran

我在一些Fortran代码中有以下行:

acc = acc + DRSite_t(u, k, s) * Exp(-(max(0.0_dp, t1 - real(s, dp)) / TAT(ds, k)))

其中DRSite_tTAT都是数组而不是函数。

显然,如果DRSite_t值为零,则不需要评估乘法运算符右侧的复杂计算。

现代编译器是否有可能接受并优化,或者我应该将其包装在if块中?

或者这是我应该吮吸它并看到的情况?如果这有任何区别,我会使用gfortran,但是如果不同的编译器会以不同的方式处理事情,那将会很有趣。

2 个答案:

答案 0 :(得分:4)

你的意思是,如果首先计算DRSite_t(u, k, s),检查它是否等于0然后可能会跳过表达式的其他部分?

我很确定编译器不这样做。在很多情况下,它会导致很多减速而不是加速。分支真的很贵。

我甚至认为,如果你手工完成,它会更慢,除非经常出现0。但编译器没有理由假设0经常发生。

答案 1 :(得分:3)

与往常一样,当浮点运算发生时,事情会变得有趣。在这种情况下,不确定0*expr是否等同于0

在IEEE算术下考虑右侧表达式的可能性。我们可以得到:

  • NaN结果,表示无限(符号)或NaN表达式;
  • 结果-0,对于支持带符号的零的负有限表达式;
  • 结果0,表示正有限值,或者当不支持带符号的零时的任何有限值。

对于前两个,可能会设置标志,这可能会导致停止。

此外,如果expr是函数引用,则该函数可能有副作用。

现在,在问题的情况下,程序员可能“知道”TAT(如果一个函数)没有副作用并且是(严格地)正值并且那里的取幂具有正的有限结果。编译器必须绝对确定,或者知道程序员不关心。

如果TAT(ds,k)无法证明(令编译器满意),那么在IEEE算法下,“优化”是错误的。

也就是说,编译器必须检查:

  • DRSite_t(u, k, s)零;和
  • 指数具有特殊值;和
  • 任何功能参考都有副作用吗?

这是很多努力,在一般情况下是不可行的。

总而言之,如果您确定0*expr确实等同于0,则值得考虑跳过整个赋值语句;但这对你来说是一个勇敢的编译器。如果TAT是一个代价高昂且功能良好的函数,那么使这个条件赋值更好的最佳机会就是。