【发布时间】:2018-01-05 08:33:54
【问题描述】:
许多消息来源说,llvm::StringMap 中使用的哈希冲突处理方法 open-addressing 不稳定。当负载因子很高(这是可以想象的)时,据说开放寻址不如链接。
但是如果负载因子低,开放寻址会造成巨大的内存浪费,因为我必须在内存中分配 Bucket_number * sizeof(Record) 个字节,即使大多数桶没有记录。
所以我的问题是,LLVM 选择开放寻址而不是分离链接的原因是什么?仅仅是因为本地缓存在速度上的优势(记录本身存储在存储桶中)吗?
谢谢:)
编辑:C++11 标准对 std::unordered_set 和 std::unordered_map 的要求暗示了链接方法,而不是开放寻址。为什么 LLVM 会选择一个连 C++ 标准都达不到的哈希冲突处理方式? llvm::StringMap 是否有任何特殊用例可以保证这种偏差? (编辑:slide deck 比较了几种 LLVM 数据结构与 STL 对应数据结构的性能)
另一个问题,顺便说一句:
llvm::StringMap 如何保证键的哈希值在增长时不会被重新计算?
manual 说:
哈希表增长不会重新计算表中已有字符串的哈希值。
【问题讨论】:
-
想必字符串不是一个大对象(只是指针+大小),所以这样你不会浪费太多内存。对于最后一个问题:也许他们将哈希值存储在表中。这样,如果字符串不匹配,比较会更快。
-
“甚至不能满足 C++ 标准”是吧?它不是
unordered_map或set。它并没有试图满足特定std容器的要求... -
@Yakk 但是如果它不能满足标准的要求,用户可以使用 std::unordered_map<:string ..> 代替 llvm::StringMap。所以我问了一些特殊的用例来证明:)
-
@geza 哦,你是对的,llvm::StringRef 只占 2 个字的长度。我的问题是普遍应用这种技术,在这种情况下 sizeof(record) 可能要大得多。
-
是的,如果 sizeof 记录很大,可能不值得。但在这种情况下,你“只是”浪费内存。它可能会更快,因为不需要指针取消引用。提示:您可以制作一个链式哈希表,其中有一个模板参数。因此,您可以选择如何存储链的第一个元素,这样您就可以对两种方式进行基准测试,并选择哪个更快
标签: c++ data-structures hash hashmap llvm