为什么Haskell不能优化这个重复的函数调用?



在我的Haskell代码中,我使用了一个经常被调用的函数,看起来像这样:

doSomething x y = (a, b)
where a = expensive1 x y
b = expensive2 x y a

用GHC 8.10.3和-O2编译,我的程序运行大约需要45秒。但是,如果我像这样编写相同的函数:

doSomething x y = (a, b)
where a = expensive1 x y
b = expensive2 x y (expensive1 x y)

我的程序运行大约需要60秒。

编译器不应该识别expensive1 x y的重复调用并优化它吗?expensive1expensive2是纯函数,所以不需要重新计算expensive1 x y。或者是GC过于激进,在需要b之前垃圾收集a?

这是一种权衡。您建议的优化减少了运行时,但增加了内存使用。每次都要自动地做出正确的权衡太难了,所以程序员被赋予了控制权——命名一个东西,它是共享的,不要命名它,它会被重新计算。

(…。这些事情总是很复杂。但这是答案的10公里视图)

顺便说一下,这个优化的名称是"公共子表达式消除"。在谷歌上搜索一下,你会得到更多关于不同编译器在这个领域的选择的信息。

最新更新