PyPy:在具有整数

时间:2017-07-11 04:14:50

标签: python performance pypy

因为我想要实现的算法使用索引1..n,并且因为它很容易将每个索引移动一个,所以我决定变得聪明并在每个列表的开头插入一个虚拟元素,所以我可以使用论文中的原始公式。

为了简洁,请考虑这个玩具示例:

def calc(N):
    nums=[0]+range(1,N+1)
    return sum(nums[1:]) #skip first element

然而,我很担心,我的结果是虚假的,因为我可以在某处偶然访问第0个元素并且不知道它。所以我变得更聪明,并使用None而不是0作为第一个元素 - 每次使用它进行算术操作都会导致运行时错误:

def calc_safe(N):
    nums=[None]+range(1,N+1) #here we use "None"
    return sum(nums[1:]) 

令人惊讶的是,这个小小的变化导致了pypy的巨大性能损失(即使使用当前的5.8版本) - 代码变得慢了大约10倍!这是我机器上的时间:

                    pypy-5.8    cpython
calc(10**8)         0.5 sec     5.5 sec
calc_safe(10**8)    7.5 sec     5.5 sec

作为副节点:Cpython不关心,是否使用None

所以我的问题有两个:

  1. 显然使用None不是一个好主意,但为什么?
  2. 是否有可能获得None - 方法的安全性并保持性能?
  3. 编辑:正如Armin所解释的那样,并非所有列表都相同,我们可以看到,通过以下方式使用了哪种策略:

    import __pypy__ 
    print __pypy__.strategy(nums)
    

    在第一种情况下,它是IntegerListStrategy,在第二种情况下是ObjectListStrategy。如果我们使用大整数值(例如2**100)而不是None,则会发生同样的情况。

1 个答案:

答案 0 :(得分:4)

PyPy对仅包含整数的列表有一个特例 - 它将它们存储为array.array。如果其中有“无”,则此优化不再有效。

这可以在PyPy中修复,以允许None作为一个特例...