【问题标题】:how to increase the efficiency of this program? [duplicate]如何提高这个程序的效率? [复制]
【发布时间】:2013-10-13 19:00:20
【问题描述】:

下面的程序(在函数prime里面)的运行时间是110.726383227秒

如果我运行相同的程序而不将它包装在一个函数(素数)中,它的运行时间是 222.006502634 秒

通过将其包装在一个函数中,我显着提高了性能。

还有没有可能提高这个程序的效率?

# This is a program to find sum of prime numbers till 2 billion

def prime():
import time
start_time = time.clock()

num = 2
j=1
tot_sum = 0

for num in xrange(2,2000000): 
    count = 0
    for j in xrange(1,int(num**0.5)+1): # checking from 1 to sqrt(n)+1
        if(num % j == 0):
            count = count+1

    if(count == 1):
        tot_sum = tot_sum + num

print "total sum is %d" % tot_sum

print time.clock() - start_time, "seconds"

【问题讨论】:

  • 使用timeit 模块来测试程序的时序而不是time.clock()
  • @hcwhsa timeit 很棒,但如果单次运行需要几分钟时间,这是不切实际的。它专为小型 sn-ps 设计。并且使用timeit 为单次跑步计时是没有用的(它使用更好的秒表,但在这个时间范围内几乎没有用处)。
  • 我认为这是因为它只需要处理本地命名空间(STORE_FAST 指令),而不是本地和全局命名空间(STORE_NAME 指令)。本地命名空间使用寄存器,而全局命名空间将其名称和对象存储在 RAM 中。不过我可能是错的。
  • 你可以用这样的技巧来调整这个程序的性能,但真正的罪魁祸首是基本算法。一个写得很好的素数筛应该几乎立即(当然不到一秒)产生高达 2000000 的素数。看stackoverflow.com/a/18049610/2192494

标签: python optimization python-2.7 performance


【解决方案1】:

如果你想在没有外部库的情况下解决它,你可以做出一些明显的改进:

def prime():
    import time
    start_time = time.clock()

    tot_sum = 2

    for num in xrange( 3, 2000000, 2 ): 
            isPrime = True
            for j in xrange(3, int( num ** 0.5 ) + 1, 2 ):
                if( num % j == 0 ):
                    isPrime = False
                    break

            if isPrime:
                tot_sum = tot_sum + num

    print "total sum is %d" % tot_sum

    print time.clock() - start_time, "seconds"

prime()

不检查大于 2 个偶数,如果找到一个则不检查所有除数。您的原始代码在我的机器上运行时间为 172.924809 秒,而我的运行时间为 8.492169 秒。

如果允许使用外部库,我建议gmpy2

def prime():
    from gmpy2 import is_prime
    import time
    start_time = time.clock()

    print "total sum is %d" % (sum(filter(is_prime, xrange(3,2000000,2)))+2)

    print time.clock() - start_time, "seconds"

prime()

这在 1.691812 秒内运行

【讨论】:

    【解决方案2】:

    这可能与 python 如何解析变量有关。粗略地说,当你输入一个函数时,python 会创建一个新的命名空间,它本质上映射到该函数本地的所有变量。然后 Python 可以使用命名空间来确定程序员正在访问的所有变量的值。变量名解析顺序如下:

    • 在本地命名空间中查找变量名
    • 在全局命名空间中查找变量名
    • 在 python 的内置函数中查找名称。

    执行查找可能会很昂贵,Python 中的一般性能提示是 use local variables 正是出于这个原因:至少,它将避免执行两次查找而不是一次。此外,较新的 python 编译器似乎也在进行额外的优化,以删除单个 lookup into the local namespace,但只是将变量视为立即值。

    测试这种优化是否仅仅因为命名空间查找而发生的一种好方法可能是(除非我不知道其他优化)将所有逻辑包装在一个函数中,但要使所有变量使用全局。如果一切都变慢了,您可能会猜到是命名空间查找花费了这么多时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      相关资源
      最近更新 更多