函数式编程语言是否有更多机会进行编译时间优化?


10

我正在读《现实世界的函数式编程》一书。它从命令式和功能性编程语言之间的比较开始。它指出了函数式编程中的“值”和“表达式”与命令式编程中的“变量”和“函数”有何不同。通过讨论,我得出了一个想法-

与命令式编程语言相比,函数式编程语言有更多机会进行编译时间优化。

是真的吗

Answers:


16

函数式编程语言可以做更多的编译时间优化。原因之一是纯度-并发是微不足道的,因为没有状态。因此,编译器可以采用两个分支并对它们进行并发,而无需更改程序的行为。

同时,可以在没有状态的情况下进行计算的任何内容(即,在haskell中为非一元形式的任何内容)都可以由编译器提前进行计算,但是这样的计算可能会很昂贵,因此可能只能部分完成。

另外,程序中不需要的任何东西都可以完全优化。


1
+1:无副作用的编程非常非常容易优化。
S.Lott

@mathepic:实际上(在Haskell中)并行化发生在编译时和运行时。编译时决定它的价值创造与否碎片(线程种子)和运行时间过程碎片,因为它可以根据您指定的线程数。如果仅指定一个线程,则会创建分片,但将一个接一个地处理它们。
Matthieu M.

2
@mathepic:纯度的另一种用途->惰性和缺乏计算能力。如果您可以证明不需要该值,则可以完全取消计算。如果可能需要,请使用一个懒惰的流。如果您知道需要使用它,请直接对其进行计算(以避免不必要的开销)。纯度(仅)惊人:)
Matthieu M.

@Matthieu好点
替代

1
@Masse甚至IO monad也很纯净。只是“运行” IO monad的结果不是。
可替代

7

原则上,函数式语言比命令式对应语言有更多的编译时优化可能性,这可能是正确的。

但是,更有趣的是,如果它们实际上是在当前的编译器中实现的,以及这些优化在实践中的相关性(即,生产环境中惯用的“ realtime(TM)”代码的最终性能,并且具有先验可预测的编译器设置)。

例如,臭名昭著的“ 计算机语言基准游戏”的Haskell提交内容(虽然可能很糟糕-但现在还不存在-那里有明显改善的地方),给人的印象是花费了大量时间手动优化面临着“由于可能的编译器优化”的主张,这insert some property about FP languages here使得该优化看起来(目前至少)比相关现实更具理论可能性。

我很高兴在这一点上被证明是错误的。


1
在Haskell中进行手动优化的原因与以下事实有关:某些“直接”操作在Haskell中有些耗时(从复杂性的角度来看)。例如,假设您要获取列表的最后一个元素。在Java中,这是一个非常简单的操作;在Haskell中,幼稚的方法要求您遍历整个列表直到结束(由于列表的惰性),使其成为O(n)操作。那是(部分地)进行手动优化的地方
。– mipadi

2
我确信,Haskell的手动优化有充分的理由,但是对于“直截了当”的操作而言,它们是必要的,这给人的印象是,优化代码的更多机会(当前)仅在理论上相关。
Alexander Battisti

6
优化算法和优化生成的代码之间的区别更大。以C为例:如果我正在编写搜索算法,则可以编写仅遍历列表的简单算法,也可以使用二进制搜索。在这两种情况下,编译器都会优化我的代码,但不会将单纯的搜索算法转换为二进制搜索。Haskell代码中的许多手动优化与优化算法本身有关,而不是优化生成的代码。
mipadi

2
@mipadi,但似乎Haskell算法的简单版本不如其他语言算法的简单版本好。(我怀疑是由于功能模型和计算机体系结构之间的不匹配而造成的)即使它擅长生成代码,也不足以克服这个问题。
Winston Ewert

>>可能不好<<-您知道它是否不好吗?您暗示它“不好”甚至意味着什么?请具体说明。
igouy 2012年

2

在函数式中,通过程序的值流非常(对于编译器和程序员)都是可见的。这使编译器有很多余地来决定值的存储位置,保留值的时间等等。

用命令式语言,编译器向程序员承诺一个模型,其中大多数变量对应于内存中的实际位置,这些位置在定义的生存期内保持不变。潜在地,任何语句都可能会读取(或写入!)这些位置中的任何一个,因此编译器只能用寄存器分配替换内存位置,将两个变量合并到单个存储位置中,或者在对位置进行细致分析之后执行类似的优化。否则程序中可能会引用该变量。

现在,有两个警告:

  • 在过去的五十年里,编程语言社区花费了大量精力(开发)进行这种分析的巧妙方法。有很多众所周知的技巧,例如套准着色等等,可以使大多数情况下更容易完成一些事情。但这会导致大型,慢速的编译器,并不断权衡编译复杂性和结果代码的质量
  • 同时,大多数函数式编程语言也不是纯函数式的。很多真正需要做的,就像对I / O响应的事情节目本身无功能,所以没有编译器可以完全自由这些技巧,也没有语言避免了它们完全-甚至Haskell中,这是一个有点纯粹出于我的口味(您的里程可能有所不同)只能控制和限制代码的非功能部分,而不能完全避免它们。

但是要回答一般性问题,是的,函数范式为编译器提供了很多自由空间来优化它在命令式设置中所没有的自由。


Haskell中的所有功能都是功能性的,只是您main是状态转换功能,而不是使用状态本身的功能。
替代

是和否-从概念上讲,Haskell程序是用户与该程序的交互(以及系统随机数生成器的状态,当今网络的时延以及其他任何固有的)的纯函数,这是完全正确的程序响应的非功能性输入),但实际上这是一个区别,没有区别。
jimwise 2011年

@jimwise引用透明性有很大的不同。
替代

除非您不是真正拥有它,至少出于此处讨论的目的。诸如IO或随机数生成之类的操作要点是,每次使用相同的输入调用它们时,它们返回不同的值,这从本质上限制了程序员编译器在功能上的推理。
jimwise 2011年

1
@mathepic是的,当然,您可以在概念上将随机性或用户输入(或网络延迟或系统负载)视为无限流或一个状态到一个状态的函数,但这并不是一个可以通过以下方式对程序行为进行有用推理的视图:您或您的编译器-鲍勃·哈珀(Bob Harper)在其博客中有关CMU的新功能编程优先CS课程的最新帖子中很好地阐述了这一点 。
jimwise 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.