【问题标题】:Performant Haskell hashed structure.高性能 Haskell 散列结构。
【发布时间】:2011-12-15 05:50:30
【问题描述】:

我正在编写执行很多表查找的程序。因此,当我偶然发现Data.Map(当然)以及Data.HashMapData.Hashtable 时,我正在仔细阅读Haskell 文档。我不是散列算法方面的专家,在检查了软件包之后,它们看起来都非常相似。因此我想知道:

1:主要区别是什么?

2:在对约 4000 个键值对的映射/表进行大量查找时,哪个性能最高?

【问题讨论】:

  • 您可能还对this blog post 感兴趣。它展示了许多有趣的数字,并比较了 Haskell 中哈希表的不同方法。该帖子得出的最终结论是,您需要杂质才能使正确的哈希表快速工作。
  • @JeremyW.Sherman SO 上的人们经常可以提供您自己无法发现的见解。例如,图书馆的作者或熟悉的人可能会偶然发现这个问题并解释晦涩的配置选项,或调整某些东西的方法。此外,有人可以推荐第四个选项SuperHashMap。最后,以后我这个职位的其他人可以看到这个问题并从中学习。
  • 一般来说,不要通过模块名来识别代码。在 Haskell 宇宙中,模块名称发生冲突。例如,当您说Data.HashMap 时,我猜您是在谈论hashmap 包,它的性能比我建议您使用的unordered-containers HashMap 实现更差。
  • @FUZxxl 谢谢你的链接。结合@mergeconflict 的回答,我说服了我尝试hashtables 包中的布谷鸟实现。另外,谢谢@ThomasM.DuBuisson,我还是 Haskell 的新手,需要这样的提示!
  • @ThomasM.DuBuisson 并不是unordered-containers 在所有方面都比hashmap 快。我使用前者的HashMap 和后者的HashSet 以在我的特定应用程序中获得最佳性能。

标签: haskell hashmap hashtable


【解决方案1】:

1:主要区别是什么?

  • Data.Map.Map 内部是平衡二叉树,所以它的查找时间复杂度是 O(log n)。我相信它是一个“persistent”数据结构,这意味着它的实现使得可变操作产生一个新副本,只更新结构的相关部分。
  • Data.HashMap.Map 在内部是一个 Data.IntMap.IntMap,它又被实现为 Patricia 树;它的查找时间复杂度是 O(min(n, W)) 其中 W 是整数中的位数。它也是“持久的”。新版本 (>= 0.2) 使用哈希数组映射尝试。根据文档:“许多操作的平均复杂度为 O(log n)。该实现使用大基数(即 16),因此在实践中这些操作是常数时间。”
  • Data.HashTable.HashTable 是一个实际的哈希表,查找的时间复杂度为 O(1)。然而,它是一个可变的数据结构——操作是就地完成的——所以如果你想使用它,你会被困在IO monad 中。

2:在对约 4000 个键值对的映射/表进行大量查找时,哪个性能最高?

很遗憾,我能给你的最佳答案是“视情况而定”。如果你从字面上理解渐近复杂性,你会得到 O(log 4000) = 大约 12 对应 Data.Map,O(min(4000, 64)) = 64 对应 Data.HashMap 和 O(1) = 1 对应 Data.HashTable。但它并没有真正这样工作......你必须在你的代码上下文中尝试它们。

【讨论】:

  • 谢谢,由于大量的文件 IO,我现在处于 IO monad 中。所有这些 IO 和哈希查找的结果都是由协程产生的,因此之后很容易逃脱 IO。我想我会给 Data.HashTable 一个机会,看看它是怎么做的。非常感谢您的帮助~
  • 没问题;还可以查看hashtables 包中的Data.HashTable.ST,上面首先由@FUZxxl 指出。
  • Patricia 树的时间复杂度 O(min(n, W)) 似乎不对……那么不如使用一个列表,不是吗?
  • 哎呀,我错了,最坏的情况是线性的。此外,Patricia 树的注释似乎在 Data.HashMap.Strict(类型 HashMap)中......
  • @mergeconflict 你好,我在哪里可以阅读haskell中详细的hashmap等数据结构的内部实现?
【解决方案2】:

Data.MapData.HashMap 的明显区别在于前者需要Ord 中的密钥,后者需要Hashable 密钥。大多数通用键都是两者,因此这不是决定性标准。我对Data.HashTable 没有任何经验,所以我无法对此发表评论。

Data.HashMapData.Map 的 API 非常相似,但 Data.Map 导出了更多的功能,有些像 alterData.HashMap 中是没有的,有些则提供了严格和非严格的变体,而Data.HashMap(我假设您的意思是来自 unordered-containers 的哈希图)在单独的模块中提供惰性和严格的 API。如果您只使用 API 的通用部分,切换真的很轻松。

关于性能,unordered-containersData.HashMap 的查找速度非常快,我上次测量时,它显然比 Data.IntMapData.Map 快,这尤其适用于 @ 的(尚未发布的)HAMT 分支987654323@。我认为对于插入,它或多或少与Data.IntMap 相当,并且比Data.Map 快一些,但我对此有点模糊。

对于大多数任务来说,两者都具有足够的性能,但对于那些性能不佳的任务,您可能无论如何都需要量身定制的解决方案。考虑到您专门询问有关查找的问题,我会给 Data.HashMap 优势。

【讨论】:

  • 确定您说的是同一个Data.Hashmap。 Unordered-containers 比其他包的 HashMap 产品快得多,我上次检查过。
  • 好点。我完全忘记了以前有一个Data.HashMap
  • 2015 年,base 中不再有 Data.HashMap。在 hashtables 包中有一个
【解决方案3】:

Data.HashTable 的文档现在说“使用hashtables 包”。有一篇很好的博客文章解释了为什么哈希表是一个很好的包here。它使用 ST monad。

【讨论】:

  • hashtables 包使用 ST monad 而不是 State monad。
  • 对,ST 只是State 的转换(即有用)版本。
  • 不,不是。存在巨大的概念差异。 ST monad 承载类型级别的状态,而 State monad 承载值级别的状态:)
猜你喜欢
  • 2013-10-16
  • 2020-03-10
  • 2012-05-26
  • 1970-01-01
  • 2014-01-19
  • 2017-06-17
  • 2019-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多