【问题标题】:Suitable object type for a 2D look-up table of unknown size created at runtime适用于在运行时创建的未知大小的 2D 查找表的对象类型
【发布时间】:2015-07-16 15:52:06
【问题描述】:

我正在编写一个 Python 3.4 脚本,它为我做了大量计算。此计算涉及计算 many many binomial coefficients,并在求和和与其他数字相乘中多次使用它们中的每一个。每次在计算中需要 bc(二项式系数)时,它都会检查 bc 是否已经计算过。如果是这样,它返回这个已经计算的值。否则,它会计算并存储它以供以后查找。目前,我的计算 bc“n 选择 k”的函数 bc(n,k) 如下所示:

bcvalues = {}

def bc(n,k):
    k = min(k,n-k) # take advantage of symmetry
    if (n,k) in bcvalues: # check whether value has already been calculated
        return bcvalues[(n,k)] # if so, return that already calculated value
    if k == 0 or n <= 1: # base case
        return 1
    result = bc(n-1,k) + bc(n-1,k-1) # Use formula for Pascal's triangle
    bcvalues[(n,k)] = result # store the value for later look-up
    return result

我的查找表是一个字典,其中 (n,k) 元组作为键,bc(n,k) 作为值。它满足所有的

严格要求

  1. 可以在运行时填充/扩展为任意大小(在计算运行之前,我不知道需要计算多少 bc,但这是一个 很多公元前)
  2. 值可以任意大(int(Python 3 之一)或gmpy2 类型mpz,我还不确定)。这很重要,因为值可能会变得非常非常大
  3. 可以用两个自然数n和k来索引
  4. 可以跳过某些元组 (n,k) 的 bc(例如,可能有 (100,50) 的条目,但没有 (100,49) 的条目)

但是,我不确定它是否是“最佳”解决方案(如果有的话)

性能要求(按重要性排序)

  1. 快速查找/读出
  2. 内存使用率低(在测试中,我的字典已经占用了几个 GB;我最终可能会在大内存机器上租用计算能力)
  3. 快速写入查找表

在我刚刚运行的非常小的输入大小测试中,函数 bc 被调用了 1600 万次,对于我真正感兴趣的输入大小,这个数字可能会增长很多。因此,性能很重要。

我当前的解决方案(字典)的优点是在计算运行结束时,我可以序列化查找表(使用 pickle),这样当我执行具有更高输入值的新运行时,我可以取消pickle它并拥有之前运行中计算的所有 bc。这是一个strong加分:

奖励积分

  1. 查找表可以轻松序列化

我的问题

除了字典,还有什么可以匹配这些条件?

我想编写一个函数,将三角形的元组 (n,k) 双射映射到自然数,然后使用一个列表作为查找表。这是多么有前途?其他想法?

【问题讨论】:

    标签: python performance python-3.x lookup memory-efficient


    【解决方案1】:

    免责声明:我维护gmpy2

    一旦您开始使用超过 50 到 100 个十进制数字的整数,您应该使用 gmpy2.mpz

    字典似乎是最好的选择。索引列表比字典查找稍快,但将 (n,k) 映射到索引值的开销使其在我的系统上变慢。

    可能有一种方法可以减少内存使用量。您递归地计算二项式系数并保存所有中间值。 bcvalues 会变得非常大。如果您不需要nk 的较小值的所有二项式系数,那么您可以尝试使用gmpy2.comb 来计算二项式系数而不保存所有中间值。

    【讨论】:

    • 感谢您的回答!我想知道 gmpy2.comb 做了什么。在哪里可以找到它的源代码?
    • @CorsinPfister 该代码是 GMP 库 (www.gmplib.org) 的一部分。 gmpy2.comb 致电 mpz_bin_ui。如果两个参数都足够小,可以使用更快的版本mpz_bin_uiui。我做了一些快速测试,它似乎确实更快。当我完成测试时,我会更新我的答案。顺便说一句,n 和 k 的值范围是多少?您是否经常重复使用相同的值?
    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 2017-07-07
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多