【问题标题】:absolute fastest lookup in python / cythonpython / cython中绝对最快的查找
【发布时间】:2014-07-21 04:34:18
【问题描述】:

我想做一个查找映射 32 位整数 => 32 位整数。

输入键不需要连续,也不需要覆盖 2^32 -1(我也不希望这个内存占用那么多空间!)。

该用例用于扑克评估器,因此必须尽可能快地进行查找。完美的散列会很好,但这可能有点超出范围。

我觉得答案是某种 cython 解决方案,但我不确定 cython 的基础以及它是否真的对 Python 的 dict() 类型有任何好处。当然,只有一个简单的偏移量跳转的平面数组会非常快,但是我在内存中为表分配了2^32 - 1 位置,这是我不想要的。

任何提示/策略?目标是在内存占用最少的情况下实现绝对速度。

【问题讨论】:

  • “最小内存的绝对速度”:您知道这里没有最佳选择,是吗?它需要令人满意的工程权衡,即(根据定义)产生一两个次优选择。如果Ignacio's answer 太占用内存,那么模块sqlite3 可能是您最好的简单替代方案。
  • 您知道您的映射将有多少条目,您是否愿意牺牲初始创建时间来加快查找速度?
  • 另外,“绝对速度”对您意味着什么?在表的整个生命周期(包括创建时间)内消耗的总 CPU 周期,还是仅用于查找的周期?
  • @NickBastin:初始创建时间不是问题,只是完成查找的时间。该表最多可以有 1.33 亿个条目。
  • 如果你的瓶颈是intint 映射,你应该使用 PyPy 并使用标准 PyPy dictPyPy is so absurdly fast for this use-case it isn't even funny.

标签: python c performance optimization cython


【解决方案1】:

你不够聪明,写得比dict快。不要难过;地球上 99.99999% 的人不是。使用dict

【讨论】:

  • 如果有帮助,初始化后的密钥空间是完全静态的 - 不需要插入。
  • 不会改变任何事情。
  • 对于许多非常具体的用例来说,编写比标准 dict 更快的东西真的不是那么难 - 甚至只是采用 dict 实现本身并对其进行优化并将其公开为新的目的。 dict 对于一般用例来说非常棒并且相当优化,但这意味着有一些权衡几乎可以惩罚每一种特定用途(可能除了一般字符串散列,dict 非常擅长)。
【解决方案2】:

首先,您应该先定义“足够快”对您来说意味着什么,然后再做其他任何事情。你总是可以让事情变得更快,所以你需要设定一个目标,这样你就不会发疯。对于这个目标来说,双头是完全合理的——比如“映射查找必须在这些参数(最小/最大/平均值)中执行,并且当/如果我们达到这些数字时,我们愿意花费 X 更多的开发时间进一步优化,但我们会停下来。”

其次,要使这更快,您应该做的第一件事是复制 Cpython 源代码树中 Objects/dictobject.c 中的代码(创建一些新的东西,例如 intdict.c 或其他东西),然后修改它,以便键是不是python对象。追求更好的散列函数可能不会很好地利用您的整数时间,但消除对您的密钥的INCREF/DECREFPyObject_RichCompareBool 调用将是一个巨大的胜利。由于您没有删除键,因此您还可以省略对虚拟值的任何检查(存在这些检查以保留已删除条目的冲突遍历),尽管您有可能通过更好的分支预测来免费获得大部分胜利你的新对象。

【讨论】:

  • 您是指cython 来源吗?在https://github.com/cython/cython?我似乎无法在那里找到Objects/dictobject.c 文件,即使使用搜索...
  • “cpython”源 - python 本身的源代码(C 实现)。您可以从默认的 dict 对象开始,然后对其进行调整以使其更快。
【解决方案3】:

您正在描述哈希索引集合的完美用例。您还描述了先写后优化策略的完美场景。

所以从 Python dict 开始。它速度很快,绝对可以完成您需要的工作。

然后对其进行基准测试。弄清楚它需要走多快,以及离你有多近。然后3个选择。

  1. 够快了。大功告成。
  2. 它几乎足够快了,比如说大约在两倍之内。编写自己的哈希索引,注意哈希函数和碰撞策略。
  3. 太慢了。你死定了。没有什么简单的事情可以让您获得 10 倍或 100 倍的改进。至少您没有在更好的哈希索引上浪费任何时间。

【讨论】:

    猜你喜欢
    • 2018-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    相关资源
    最近更新 更多