【问题标题】:Good introductory text about GHC implementation?关于 GHC 实施的好的介绍性文字?
【发布时间】:2011-08-28 05:43:17
【问题描述】:

在 Haskell 中编程时(尤其是在解决 Project Euler 问题时,次优的解决方案往往会对 CPU 或内存需求造成压力),我经常对为什么程序的行为方式感到困惑。我查看配置文件,尝试引入一些严格性,选择另一种数据结构,......但大多是在黑暗中摸索,因为我缺乏良好的直觉。

另外,虽然我知道 Lisp、Prolog 和命令式语言的典型实现方式,但我不知道如何实现惰性语言。我也有点好奇。

因此,我想更多地了解从程序源到执行模型的整个链条。

我想知道的事情:

  • 应用了哪些典型优化?

  • 当有多个评估候选者时,执行顺序是什么(虽然我知道它是由所需的输出驱动的,但先评估 A 再评估 B 或先评估 B 以检测可能仍然存在很大的性能差异你根本不需要A)

  • thunk 是如何表示的?

  • 栈和堆是如何使用的?

  • 什么是 CAF? (分析有时表明热点在那里,但我不知道)

【问题讨论】:

  • 不完全是我所说的介绍性,但SPJ's book on the implementation of functional languages 是一本好书。
  • Uuhh.. 对我来说,这是对 GHC 研究人员发表的大量论文的深入挖掘。如果您对数据表示感兴趣,Edward Z. Yang 的 series of blog posts 可能对您很感兴趣。
  • 这是我一直想问的问题。熟悉论文是一个好的开始。它们是可读的。你可能对垃圾收集感兴趣,因为它们揭示了大部分底层结构(闭包块是如何实现的)。对于不同的编译器通道,我不知道。
  • 关于第二项,如果A真的只用于B的某些值,那么A将在B之后评估或根本不评估,因为从未被评估过强迫?除非有其他东西造成了不必要的严格性,在这种情况下,即使 A 无论如何都不需要,也可能会被评估。

标签: optimization compiler-construction haskell ghc heap-memory


【解决方案1】:

这可能不是您在介绍性文本中所想的,但 Edward Yang 有一系列博客文章正在讨论 Haskell 堆、如何实现 thunk 等。

这很有趣,既有插图,也有对 Haskell 新手的解释,无需深入研究太多细节。该系列涵盖了您的许多问题:

在更技术层面上,有许多论文涵盖(与其他事物一致),您想知道的部分内容。:

  • A paper by SPJ, Simon Marlow et al on GC in Haskell - 我还没读过它,但由于 GC 通常代表了 Haskell 所做工作的一个很好的部分,它应该提供洞察力。
  • The Haskell 2010 report - 我相信你一定听说过这个,但不链接到太好了。可以在某些地方进行枯燥的阅读,但这是了解 Haskell 为何如此的最佳方式之一,至少是我读过的部分。
  • A history of Haskell - 比名称所暗示的更具技术性,并为 Haskell 的设计和设计背后的决策提供了一些非常有趣的观点。看完Haskell的实现会让你不由得更加了解。

【讨论】:

    【解决方案2】:

    有关 GHC 系统的架构和方法的大部分技术信息都在他们的 wiki 中。我将链接到关键部分,以及一些人们可能不知道的相关论文。

    应用了哪些典型优化?

    这方面的关键论文是:A transformation-based optimiser for Haskell, SL Peyton Jones 和 A Santos,1998 年,描述了 GHC 使用的模型,该模型通过应用核心类 Haskell 语言的类型保留转换(重构)来改善时间和内存使用。这个过程称为“简化”。

    在 Haskell 编译器中完成的典型事情包括:

    • 内联;
    • Beta 减少;
    • 死代码消除;
    • 条件转换:case-of-case、case elimination。
    • 拆箱;
    • 构造产品退货;
    • 完全惰性转换;
    • 专业化;
    • Eta 扩展;
    • Lambda 提升;
    • 严格性分析。

    有时:

    • 静态参数转换;
    • 构建/折叠或流融合;
    • 通用子表达式消除;
    • 构造函数专业化。

    上述论文是开始理解大部分优化的关键所在。较早的书Implementing Functional Languages、Simon Peyton Jones 和 David Lester 中给出了一些更简单的方法。

    当有多个候选评估时执行顺序是什么

    假设您使用的是单处理器,那么答案是“编译器根据启发式方法和程序的需求模式静态选择的某种顺序”。如果您通过 sparks 使用推测性评估,那么“一些不确定的、无序的执行模式”。

    一般来说,要查看执行顺序是什么,请查看核心,例如ghc-core 工具。 introduction to Core 在 RWH 优化章节中。

    thunk 是如何表示的?

    thunk 表示为带有代码指针的堆分配数据。

    the layout of heap objects。 具体见how thunks are represented

    栈和堆是如何使用的?

    the design of the Spineless Tagless G-machine 确定,具体而言,自该论文发布以来进行了许多修改。概括地说,执行模型:

    • (装箱的)对象在全局堆上分配;
    • 每个thread object has a stack,由与堆对象布局相同的帧组成;
    • 进行函数调用时,将值压入堆栈并跳转到函数;
    • 如果代码需要分配,例如构造函数,该数据被放置在堆上。

    要深入了解堆栈使用模型,请参阅"Push/Enter versus Eval/Apply"

    什么是 CAF?

    “恒定应用形式”。例如。为程序执行的整个生命周期分配的程序中的顶级常量。因为它们是静态分配的,所以它们必须是treated specially by the garbage collector


    参考资料和延伸阅读

    【讨论】:

    • 老实说,我不知道您是如何抽出时间来提供这么多详细、图解、参考充分的答案,但我很高兴您这样做 :)
    • 大部分内容都缓存在我多年读研究生的脑海中 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 2012-05-27
    相关资源
    最近更新 更多