两个操作的性能,以获得前n个自然数的总和

时间:2014-08-29 07:46:04

标签: python performance math

我正在研究Project Euler problem 12并提出以下解决方案:

import math

def main():
    num = 0
    j = 0
    numFactors = 0
    while numFactors <= 500:
        j += 1


        num = num + j #num = sum of numbers from 1 to j
        #num = (j *(j+1))//2


        numFactors = 0
        for n in range(1,int(math.sqrt(num))):
            if num % n == 0:
                numFactors += 2

    print(num)

if __name__ == '__main__':
    from timeit import Timer
    t = Timer(lambda: main())
    print(t.timeit(number=1))

我的问题是针对num = num + j的{​​{1}}行。

当仅使用单个加法时,程序始终比我取消注释下一行并执行乘法,加法和除法时要慢。

任何人都可以解释为什么单一操作比做3更慢?

1 个答案:

答案 0 :(得分:1)

我实际上并没有发现我的机器性能有任何差异。如果乘法实际上比加法更快,我也会感到中庸。

我们可以使用dis module来反汇编两个变体中的字节代码。两种变体中的大部分都是相同的,因此两种功能中的性能应该相同。这两个部分是不同的(第11行是num = num + j,第12行是num = (j *(j+1))//2):

 11          43 LOAD_FAST                0 (num)
             46 LOAD_FAST                1 (j)
             49 BINARY_ADD          
             50 STORE_FAST               0 (num)

 12          43 LOAD_FAST                1 (j)
             46 LOAD_FAST                1 (j)
             49 LOAD_CONST               3 (1)
             52 BINARY_ADD          
             53 BINARY_MULTIPLY     
             54 LOAD_CONST               4 (2)
             57 BINARY_FLOOR_DIVIDE 
             58 STORE_FAST               0 (num)

两个拆卸中都有三个操作。这里再次显示每个变体的唯一线:

 11          43 LOAD_FAST                0 (num)

 12          43 LOAD_FAST                1 (j)
             49 LOAD_CONST               3 (1)
             53 BINARY_MULTIPLY     
             54 LOAD_CONST               4 (2)
             57 BINARY_FLOOR_DIVIDE

如果乘法真的比加法快,那么我希望精通字节码的人可以解释为什么LOAD_FAST num比第12行的五个操作快。但是我的外行人看来,我希望使用更多字节码操作的变体需要更长的时间。