Haskell中的快速数据结构

时间:2012-09-11 21:52:23

标签: haskell containers ghc

我发现在containers包中,Data.MapData.IntMap等关键数据结构是在纯Haskell中实现的。 问:我想知道,在C中实施它们会不会更有效率?我知道ghc非常好但绝对不能与优化的C代码竞争。

3 个答案:

答案 0 :(得分:10)

这是一个有趣的问题,但我不确定是否有人能够以某种方式提供任何结论性答案(除了设计和构建广泛的测试套件并生成大量数字)

这个问题背后的假设似乎是“C总是很快,Haskell总是很慢,所以用C而不是Haskell编写代码不是更好吗?”我不确定这个假设是否真实准确。 (在我有限的经验中,并不是Haskell 慢,而是Haskell 可能慢 - 或者非常快 - 并且预测很尴尬你将获得什么样的速度。)

通过FFI调用C会产生开销。 Haskell数据结构由垃圾收集器处理;通过C使用的内存必须手动管理。你在这里看到了相当多的努力,可能没有你想象的那么多。

由于可变性,C数据结构往往更有效。大多数人不想在Haskell中使用可变数据结构。 (在某种意义上,它首先否定了使用Haskell的所有好处,所以为什么要麻烦?)如果你在C中使用不可变数据结构,你甚至可能会发现它比Haskell慢。 (例如,我被告知C在动态内存分配方面相当慢,这对于持久数据结构来说是一个问题。另一种方法是复制所有地方的东西,这也不会要快。)

最重要的是,GHC会进行巧妙的优化,例如砍伐森林,这有时会导致容器在运行时完全消失。 C编译器永远不会做这样的事情。而Haskell,作为一种懒惰的语言,有时可以完全跳过你要求它做的工作;如果容器是用C实现的,那就无法工作。

总而言之,“看起来”在C中实现这些东西应该“显然”要快得多。实际上,我怀疑答案并不是那么明确。

答案 1 :(得分:5)

GHC的运行时优化用于有效分配不可变结构。它通常会在此任务中击败C运行时(malloc)。因此,C主要用于优化算法,而不是数据结构。一个例外是非常低级别的数据结构或高度可调的可变结构。

答案 2 :(得分:4)

首先,Data.Map不是通常的命令式地图,而是所谓的持久性地图。它应该支持有效保持自身的多个版本。 C不适合这种类型的数据结构 - 例如,传统的C风格内存管理是不可能的。

其次,GHC堆布局非常复杂,尤其是在使用Ord a字典进行比较的情况下。因此,与旧的优质C接口并不简单,接口成本可能会超出所谓的更好代码生成的优势。

在C语言中实现Data.Map是可能的,但由于所有这些簿记,它几乎没有帮助。您可以尝试让我们知道它是否更快:)正如您所看到的,它还没有完成,因为社区非常确定无法做任何事情。