【问题标题】:Quick 64bit integer ID Lookup/Search快速 64 位整数 ID 查找/搜索
【发布时间】:2011-01-28 11:04:30
【问题描述】:

我正在开发一款游戏,为了安全起见,任何用户(程序员)只能将 ID 存储到对象而不是指针,并且必须使用此 ID 来获取指向对象的指针,以便必须有一些高质量的独处时间。

让我们使用最坏的情况:每个 ID 都在使用中。它是 64 位的,所以你可以去:18446744073709551616 个 ID 进行搜索。很多数据都存储在数据库中,我们的程序查找要么返回一个指针,要么返回一个空指针。空指针意味着程序必须访问数据库才能加载对象,之后它将有一个指针。

想法: 所以我在这里知道的唯一真正的技巧是二进制搜索。因此,在最坏的情况下,这意味着每次 ID 查找要进行 64 次比较。

我的另一个想法是创建一个静态空间分区,这是一棵树,其中每个分支都分成 2 次方的分支,但只到合理的深度。在 ID 上使用按位运算符而不是模运算符来找出它在每个级别上属于哪个分支。树中每个可能的分支总是存在的,但在某个深度它们会停止,并且仍然需要进行二分搜索,因为值的确切数量仍然未知。

你有什么想法?

【问题讨论】:

    标签: c++ search map lookup


    【解决方案1】:

    这是哈希映射的经典案例。首先,了解您在任何时候实际上可以激活多少个 ID。 2^64 是无稽之谈,因为那时即使只是保存这些 ID 的数据结构和指向对象的指针也至少已经是 268'435'456 TB。现在,使用 64 位 ID 并没有什么问题,但要弄清楚在任何时候您将拥有多少活动对象,选择一个合理的数字,例如 5'000,并使用对象数量的 10 倍的哈希映射。如果您的负载因子足够低并且您的哈希函数足够好,您将获得平均 O(1) 访问时间。

    【讨论】:

    • 是的,现在我明白了我的想法是多么愚蠢:也许 ID 空间允许 2^64 种可能性,但所有对象都不会以任何方式全部加载到内存中。谢谢,而且,我现在有点惭愧;(,对不起。
    【解决方案2】:

    即使活动对象的数量会大得多,比如 100 万,您仍然可以使用相对较小的哈希映射,例如大小为 10000 的映射。映射的每个元素都指向一个 ID 链表。这些列表使用简单的线性搜索进行搜索。如果散列函数选择得当,ID 将均匀(或接近)分布在散列映射中的 10000 个条目上。因此,哈希表的每个条目将包含大约 100 个 ID。线性搜索这样一个列表平均需要 50 次比较。

    在我的一个应用程序中,符号数量约为 1000。我只使用了简单的线性搜索。性能分析表明,90% 的 CPU 时间都花在了查表上。接下来我制作了一个只有 32 个条目的哈希表 -> 表查找的 CPU 负载降至 4% 以下。问题解决了。扩大哈希表对速度没有明显影响(小于 4%),所以我将其保留为 32。

    结论:可以使用小于元素数量的哈希表。这需要(ID 总数 / 哈希表大小 / 2)的平均比较次数 选择足够大的哈希表大小以将查找表的 CPU 时间减少到总 CPU 时间的一小部分。

    【讨论】:

    • +1 指出在较高负载率下的良好解决方案。应该注意的是,链表强加了一个额外的间接级别,因此更多的缓存未命中。这是可用内存和性能要求之间的平衡。
    【解决方案3】:

    “你有什么想法?”

    我会先使用std::map,如果性能不佳,我只会考虑实施我自己的解决方案。

    http://www.cplusplus.com/reference/stl/map/

    【讨论】:

      猜你喜欢
      • 2016-02-09
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2011-01-22
      • 2012-07-28
      相关资源
      最近更新 更多