gpt4 book ai didi

python - divmod() 是否比使用 % 和//运算符更快?

转载 作者:IT老高 更新时间:2023-10-28 22:24:14 25 4
gpt4 key购买 nike

我记得在汇编中整数除法指令会产生商和余数。因此,在 python 中,内置的 divmod() 函数会比使用 %// 运算符更好(假设当然需要商和余数)?

q, r = divmod(n, d)
q, r = (n // d, n % d)

最佳答案

测量就是知道(Macbook Pro 2.8Ghz i7 上的所有计时):

>>> import sys, timeit
>>> sys.version_info
sys.version_info(major=2, minor=7, micro=12, releaselevel='final', serial=0)
>>> timeit.timeit('divmod(n, d)', 'n, d = 42, 7')
0.1473848819732666
>>> timeit.timeit('n // d, n % d', 'n, d = 42, 7')
0.10324406623840332

divmod() 函数在这里处于劣势,因为您每次都需要查找全局。将其绑定(bind)到本地(timeit 时间试验中的所有变量都是本地的)可以稍微提高性能:

>>> timeit.timeit('dm(n, d)', 'n, d = 42, 7; dm = divmod')
0.13460898399353027

但运算符(operator)仍然获胜,因为在执行对 divmod() 的函数调用时,他们不必保留当前帧:

>>> import dis
>>> dis.dis(compile('divmod(n, d)', '', 'exec'))
1 0 LOAD_NAME 0 (divmod)
3 LOAD_NAME 1 (n)
6 LOAD_NAME 2 (d)
9 CALL_FUNCTION 2
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
>>> dis.dis(compile('(n // d, n % d)', '', 'exec'))
1 0 LOAD_NAME 0 (n)
3 LOAD_NAME 1 (d)
6 BINARY_FLOOR_DIVIDE
7 LOAD_NAME 0 (n)
10 LOAD_NAME 1 (d)
13 BINARY_MODULO
14 BUILD_TUPLE 2
17 POP_TOP
18 LOAD_CONST 0 (None)
21 RETURN_VALUE

//% 变体使用更多的操作码,但是 CALL_FUNCTION 字节码在性能方面是一个熊。


在 PyPy 中,对于小整数并没有太大的区别;操作码的小速度优势在 C 整数运算的绝对速度下消失了:

>>>> import platform, sys, timeit
>>>> platform.python_implementation(), sys.version_info
('PyPy', (major=2, minor=7, micro=10, releaselevel='final', serial=42))
>>>> timeit.timeit('divmod(n, d)', 'n, d = 42, 7', number=10**9)
0.5659301280975342
>>>> timeit.timeit('n // d, n % d', 'n, d = 42, 7', number=10**9)
0.5471200942993164

(我不得不将重复次数提高到 10 亿次以显示差异到底有多小,PyPy 在这里速度非常快)。

但是,当数字变得时,divmod() 以国家英里数获胜:

>>>> timeit.timeit('divmod(n, d)', 'n, d = 2**74207281 - 1, 26', number=100)
17.620037078857422
>>>> timeit.timeit('n // d, n % d', 'n, d = 2**74207281 - 1, 26', number=100)
34.44323515892029

(与霍布斯的数字相比,我现在必须将重复次数调低 10 倍,以便在合理的时间内获得结果)。

这是因为 PyPy 不再能够将这些整数拆箱为 C 整数;您可以看到使用 sys.maxintsys.maxint + 1 之间的显着时间差异:

>>>> timeit.timeit('divmod(n, d)', 'import sys; n, d = sys.maxint, 26', number=10**7)
0.008622884750366211
>>>> timeit.timeit('n // d, n % d', 'import sys; n, d = sys.maxint, 26', number=10**7)
0.007693052291870117
>>>> timeit.timeit('divmod(n, d)', 'import sys; n, d = sys.maxint + 1, 26', number=10**7)
0.8396248817443848
>>>> timeit.timeit('n // d, n % d', 'import sys; n, d = sys.maxint + 1, 26', number=10**7)
1.0117690563201904

关于python - divmod() 是否比使用 % 和//运算符更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30079879/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com