您如何编写GHC中尽可能高效的数据结构?

时间:2011-06-21 21:35:26

标签: data-structures haskell

所以有时我需要编写一个我在Hackage上找不到的数据结构,或者我发现的数据结构没有经过测试或质量不足以让我信任,或者它只是我不想成为依赖项的东西。我现在正在阅读Okasaki的书,它非常擅长解释如何设计渐近快速的数据结构。

但是,我正在专门研究GHC。常数因素对我的应用来说是一个大问题。内存使用对我来说也是一个大问题。所以我对GHC有特别的疑问。

特别是

  • 如何最大化节点共享
  • 如何减少内存占用
  • 如何避免由于严格不严/懒惰造成的空间泄漏
  • 如何让GHC为代码的重要部分生成紧密的内部循环

我浏览了网络上的各个地方,我对如何使用GHC有一个含糊的想法,例如,使用UNPACK pragma查看核心输出,等等。但我不确定我明白了。

所以我弹出了我最喜欢的数据结构库,容器,并查看了Data.Sequence模块。我不能说我理解他们正在做的很多事情,以使Seq快速。

引起我注意的第一件事是FingerTree a的定义。我认为这只是我对手指树不熟悉。引起我注意的第二件事是所有SPECIALIZE pragma。我不知道这里发生了什么,我很好奇,因为这些都遍布整个代码。

许多函数也有一个INLINE pragma与它们相关联。我可以猜到这意味着什么,但我如何判断何时INLINE函数?

事情变得非常有趣~~475,一个被称为'应用建筑'的部分。他们定义了一个newtype包装器来表示Identity monad,他们编写自己的严格状态monad副本,并且他们有一个名为applicativeTree的函数,它显然专门用于Identity monad,这增加了输出的共享功能。我不知道这里发生了什么。什么巫术被用来增加分享?

无论如何,我不确定从Data.Sequence中学到很多东西。是否有其他“模范程序”我可以阅读以获得智慧?我真的很想知道当我真正需要它们更快时,如何更新我的数据结构。有一件事特别是编写使融合变得容易的数据结构,以及如何编写好的融合规则。

2 个答案:

答案 0 :(得分:41)

这是一个很大的话题!大多数已在其他地方解释过,所以我不打算在这里写一本书章。代替:

  • Real World Haskell,第25章,“Performance” - 讨论分析,简单专业化和解包,阅读Core以及一些优化。

Johan Tibell在这个主题上写了很多:

从这里开始的一些事情:

还有其他一些事情:

答案 1 :(得分:13)

applicativeTree非常花哨,但主要是以与FingerTrees有关的方式,这本身就是一个非常奇特的数据结构。我们讨论了错综复杂的问题over at cstheory。请注意,applicativeTree编写为适用于任何 Applicative。它恰好发生在它专用于Id时,它可以以其它方式共享节点。您可以通过内联Id方法并查看发生的情况来自行完成专业化。请注意,此专门化仅在一个位置使用 - O(log n)replicate函数。事实上,更通用的功能专门针对常量情况,这是一个非常聪明的代码重用,但实际上就是这一切。

总的来说,我认为Sequence教授更多关于设计持久数据结构的知识,而不是关于实现性能的所有技巧。 Dons的建议当然很棒。我还要浏览真正的规范和调优库的来源 - MapIntMapSetIntSet in特定。与此同时,值得一看米兰的paper on his improvements to containers