我怎么知道为什么运行我的代码需要太长时间?

时间:2014-04-26 13:57:26

标签: python time-complexity

我知道我的代码的复杂性不是最好的,我认为它可能需要3到6分钟的运行时间,但我给了它15分钟并且它没有停止。 我如何知道它是否卡在某处或者它仍在运行? 我该如何改进呢?

import random
import time 
def is_prime(m):
    """ probabilistic test for compositeness of m>30
    adds a trivial sieve to quickly eliminate divisibility
    by small primes. """
    if m in [2,3,5,7,11,13,17,19,23,29]:
        return True    # treats small primes separately
    for prime in [2,3,5,7,11,13,17,19,23,29]:
        if m % prime == 0:
            return False
    for i in range(0,100):
        a = random.randint(1,m-1) # a is a random integer in [1..m-1]
        if pow(a,m-1,m) != 1:
                return False
    return True


def order_safe_prime(g,p):

    """ computes the order of g modulo a safe prime, p """
    if g<1 or g>p-1:
        return str.format("g={} is out of range", g)
    elif not is_prime(p):
        return str.format("{} is not a prime", p)
    q=(p-1)//2
    if not is_prime(q):
        return str.format("q={} is not a prime", (p-1)//2)
    else:
        if g==1:
            return 1
        if g==p-1:
            return 2
        if pow(g,q,p)==1:
            return q
        if pow(g,p-1,p)==1:
            return p-1



def stats_ord_secure(p,times=10000):
    cnt1=0
    cnt2=0
    for i in range(times):
        g=random.randint(2,p-2)
        if order_safe_prime(g,p)==(p-1)/2:
            cnt1+=1
        if order_safe_prime(g,p)==(p-1):
            cnt2+=1
    return ((cnt1/times,cnt2/times))

例如跑步:

>>>stats_ord_secure((2**1001)+188151)

需要超过15分钟!

1 个答案:

答案 0 :(得分:0)

除了分析之外,您还可以在某处添加一个print语句,以查看何时到达某些代码。例如,在stats_ord_secure中,您可以在循环开头放置一个print,以了解每次迭代需要多长时间:

for i in range(times):
    print('loop')

这样做,您可以快速看到单次迭代需要几秒钟。如果您将其乘以times 10000,则可以很容易地了解为什么需要这么长时间。

对于单次迭代,这是分析器给我的:

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      402    2.129    0.005    2.129    0.005 {pow}
      401    0.002    0.000    0.006    0.000 random.py:173(randrange)
        4    0.002    0.001    2.128    0.532 profile-test.py:4(is_prime)
        1    0.002    0.002    2.144    2.144 profile-test.py:1(<module>)
        1    0.002    0.002    0.004    0.004 random.py:40(<module>)
        1    0.001    0.001    0.001    0.001 {nt.urandom}
      401    0.001    0.000    0.003    0.000 random.py:242(_randbelow)
      768    0.001    0.000    0.001    0.000 {method 'getrandbits' of '_random.Random' objects}
      403    0.001    0.000    0.001    0.000 {math.log}
        1    0.001    0.001    0.001    0.001 hashlib.py:55(<module>)
      401    0.001    0.000    0.006    0.000 random.py:236(randint)
        1    0.000    0.000    2.138    2.138 profile-test.py:42(stats_ord_secure)
        1    0.000    0.000    0.000    0.000 __future__.py:48(<module>)
        2    0.000    0.000    2.138    1.069 profile-test.py:20(order_safe_prime)

正如您所看到的,花费的时间最多的是pow,您拨打的电话数量非常大。