简体   繁体   English

Haskell中的WHNF减少是否发生在编译时?

[英]Does the WHNF reduction in Haskell happen at Compile time?

AFAIU the object file generated by Haskell compiler should be machine code. AFAIU由Haskell compiler生成的目标文件应该是机器代码。 So does that object file have a representation of the original AST and reduces it at run time or does this reduction happen at compile time and only final WHNF values are converted to the corresponding machine code. 那么该目标文件是否具有原始AST的表示并在运行时减少它,或者这种减少是在编译时发生的,并且只有最终的WHNF值被转换为相应的机器代码。

I understand the compilation time of latter would be a function of the time complexity of program itself which I think is less likely. 我理解后者的编译时间是程序本身时间复杂度的函数,我认为不太可能。

Can someone give a clear explanation of what happens at run time and what happens at compile time in the case of Haskell (GHC) ? 有人可以清楚地解释运行时会发生什么以及在Haskell (GHC)的情况下编译时会发生什么?

A compiler could perform its job performing all the reduction at runtime. 编译器可以在运行时执行其所有减少的工作。 That is, the resulting executable could have a (large) data section, where the whole program AST is encoded, and a (small) text/code section with a generic WHNF reducer which operates on the AST. 也就是说,生成的可执行文件可以具有(大)数据部分,其中整个程序AST被编码,以及(小)文本/代码部分具有在AST上操作的通用WHNF缩减器。

Note that the above approach would work in any language. 请注意,上述方法适用于任何语言。 Eg a Python compiler could also generate an executable file comprising AST data and generic reducer. 例如,Python编译器也可以生成包含AST数据和通用reducer的可执行文件。 The reducer would follow the so-called small-step semantics of the language, which is a very well known notion in computer science (more specifically, in programming languages theory). reducer将遵循语言的所谓小步语义 ,这是计算机科学中更为人熟知的概念(更具体地说,在编程语言理论中)。

However, the performance of such approach would be quite poor. 但是,这种方法的表现会很差。

Researchers in programming languages worked on finding better approaches, resulting in the definition of abstract machines . 编程语言的研究人员致力于寻找更好的方法,从而导致抽象机器的定义。 Essentially, an abstract machine is an algorithm for running an high level program in a lower level setting. 本质上,抽象机是用于在较低级别设置中运行高级程序的算法。 Usually, it exploits a few data structures (eg stacks) to make the process more efficient. 通常,它利用一些数据结构(例如堆栈)来使过程更有效。 In the case of functional languages such as Haskell, well known abstract machines include: 对于Haskell等函数式语言,众所周知的抽象机器包括:

The problem itself is far from being trivial. 问题本身远非微不足道。 There has been, and I'd say there still is, research on making WHNF reduction more efficient. 已经有,并且我认为仍有研究使WHNF降低效率更高。

Each Haskell definition, after GHC compilation, becomes a sequence of assembly instructions, which manipulate the state of the STG machine. 在GHC编译之后,每个Haskell定义都成为一系列汇编指令,它们操纵STG机器的状态。 There is no AST around, only code which manipulates data / closures / etc. 周围没有AST,只有操作数据/闭包等的代码。

One could say that it is very important to use such advanced techniques to improve performance, coupled with heavy optimizations. 可以说,使用这些先进技术来提高性能以及大量优化是非常重要的。 A negative consequence, though, is that it becomes hard to understand the performance of the resulting code from the original one, since one needs to take into account how the abstract machine works (which is non trivial) and the optimizations (which are quite complex nowadays). 然而,一个消极的后果是,很难理解原始代码的结果代码的性能,因为需要考虑抽象机器的工作方式(这是非常重要的)和优化(非常复杂)如今)。 To some lesser extent, this is also the case for heavily optimizing C or C++ compilers, where it becomes harder to know when the optimization was triggered or not. 在较小程度上,这也是大量优化C或C ++编译器的情况,在这种情况下,更难以了解何时触发优化。

Ultimately, an experienced programmer (in Haskell, C, C++, or anything else) will come to understand the basic optimizations of their compiler, and the basic mechanisms abstract machine which is being used. 最终,有经验的程序员(在Haskell,C,C ++或其他任何方面)将会理解其编译器的基本优化,以及正在使用的抽象机器的基本机制。 However, this is not something which is easy to master, I think. 但是,我认为这不是一件容易掌握的事情。

In the question, it is mentioned that WHNF reduction could be performed at compile time. 在这个问题中,提到WHNF减少可以在编译时执行。 This is only partially true, since the value of the variables originating from IO actions can not be known until runtime, so reduction can only happen at runtime when it involves those values. 这只是部分正确,因为直到运行时才能知道源自IO动作的变量的值,因此减少只能在涉及这些值的运行时发生。 Further, performing reduction can also make performance worse! 此外,执行减少也会使性能变差! Eg 例如

let x = complex computation in x + x
-- vs
complex computation + complex computation

The latter is the result of reducing the former, but it duplicates work! 后者是减少前者的结果,但它重复了工作! Indeed, most abstract machines use a lazy reduction approach that makes x to be computed only once in such cases. 实际上,大多数抽象机器都使用惰性约简方法,这使得x在这种情况下只能计算一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM