【问题标题】:How effective is compiler common subexpression elimination?编译器公共子表达式消除的效果如何?
【发布时间】:2017-02-06 12:03:30
【问题描述】:

我需要计算一些包含公共子表达式的相当长的表达式。例如,考虑以下两个表达式:

double dfdx1 = 2 * (-x2 + x1 - sin(b2)*n34 + cos(b2)*sin(c2)*n24 - cos(b2)*cos(c2)*n14 + sin(b1)*m34 - cos(b1)*sin(c1)*m24 + cos(b1)*cos(c1)*m14);

double dfdx2 = -2 * (-x2 + x1 - sin(b2)*n34 + cos(b2)*sin(c2)*n24 - cos(b2)*cos(c2)*n14 + sin(b1)*m34 - cos(b1)*sin(c1)*m24 + cos(b1)*cos(c1)*m14);

除了消除所有三角函数之外,一个明显的消除是dfdx2 = -dfdx1。问题是编译器是否会认识到这一点。我发现使用 MATLAB 的 MuPad generate::optimize() 函数没有,这让我很惊讶。

更一般地说,编译器会在下面的示例中识别出f2 = -f1

double f1 = a*a + b*b - c*a - c*b;
double f2 = c*a + c*b - a*a - b*b;

或者它会直接删除 a*ab*bc*ac*b 等术语吗?

我正在使用 MSVC 编译器,但我猜它们都做几乎相同的事情。

【问题讨论】:

    标签: compiler-optimization


    【解决方案1】:

    如果您启用“快速数学”(gcc 的-ffast-math),通常编译器应该识别这一点并执行所要求的转换。原因是浮点运算并不完全准确,表达式的计算顺序可能很重要。

    示例(对于双精度,所有常量实际上都被认为是其他操作的结果):

    "1e100"+"1.0"-"1e100" results in 0.0 
    
    "1e100"-"1e100"+"1.0" results in 1.0
    

    因此,如果您明确允许此类转换,编译器只会重新排序表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-11
      • 2016-07-03
      • 2014-01-13
      • 2014-07-12
      • 1970-01-01
      相关资源
      最近更新 更多