为什么我的Eratosthenes筛在整数上比布尔运算更快?

2024-10-04 09:26:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我写了一个简单的Eratosthenes筛,它使用一个1的列表,如果不是质数,就把它们变成0,就像这样:

def eSieve(n): #Where m is fixed-length list of all integers up to n
    '''Creates a list of primes less than or equal to n'''
    m = [1]*(n+1)
    for i in xrange(2,int((n)**0.5)+1):
        if m[i]:
            for j in xrange(i*i,n+1,i):
                m[j]=0
    return [i for i in xrange(2,n) if m[i]]

我测试了它的速度,得到:

^{pr2}$

我假设,如果我把[1]0改成布尔函数,它会运行得更快。。。但事实恰恰相反:

#n: t
#10**1: 7.31 μs
#10**2: 29.5 μs
#10**3: 297 μs
#10**4: 2.99 ms
#10**5: 29.9 ms
#10**6: 331 ms
#10**7: 3.7 s

为什么布尔人变慢了?在


Tags: oftoin列表forifisdef
1条回答
网友
1楼 · 发布于 2024-10-04 09:26:54

发生这种情况是因为在Python2中,True和{}是作为全局变量查找的。01文本只是常量,通过快速数组引用查找,而全局变量则是全局命名空间中的字典查找(通过内置命名空间):

>>> import dis
>>> def foo():
...     a = True
...     b = 1
... 
>>> dis.dis(foo)
  2           0 LOAD_GLOBAL              0 (True)
              3 STORE_FAST               0 (a)

  3           6 LOAD_CONST               1 (1)
              9 STORE_FAST               1 (b)
             12 LOAD_CONST               0 (None)
             15 RETURN_VALUE        

使用LOAD_GLOBAL字节码查找True值,而使用1字节码将1文本值复制到堆栈中。在

如果您生成TrueFalse局部变量,则可以同样快速地使它们:

^{pr2}$

TrueFalse指定为for参数的默认值,使函数将这些名称作为局部变量,具有完全相同的值;同样使用简化版本:

>>> def bar(True=True, False=False):
...     True == False
... 
>>> dis.dis(bar)
  2           0 LOAD_FAST                0 (True)
              3 LOAD_FAST                1 (False)
              6 COMPARE_OP               2 (==)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

注意LOAD_FAST操作码,现在的索引与LOAD_CONST字节码相同;CPython函数中的局部变量与字节码常量一样存储在数组中。在

有了这种变化,使用布尔函数会胜出,尽管差距很小;我的时间安排:

# n      integers  globals  locals
# 10**1  4.31 µs   4.2 µs   4.2 µs
# 10**2  17.1 µs   17.3 µs  16.5 µs
# 10**3  147 µs    158 µs   144 µs
# 10**4  1.5 ms    1.66 ms  1.48 ms
# 10**5  16.4 ms   18.2 ms  15.9 ms
# 10**6  190 ms    215 ms   189 ms   
# 10**7  2.21 s    2.47 s   2.18 s

差别并不是很大,因为Python布尔函数只是一个int子类。在

请注意,在python3中,True和{}已经成为关键字,不能再赋值给它们,因此可以像对待整数文本一样对待它们。在

相关问题 更多 >