检查我的以下代码;它是在python中实现的sigma_2函数(使用原始筛选)的一部分,它是除数函数之一http://mathworld.wolfram.com/DivisorFunction.html
from time import time
from itertools import count
import numpy
def sig2(N, nump=False):
init = time()
#initialize array with value=1 since every positive integer is divisible by 1
if nump:
print 'using numpy'
nums = numpy.ones((N,), dtype=numpy.int64)
else:
nums = [1 for i in xrange(1, N)]
#for each number n < N, add n*n to n's multiples
for n in xrange(2, N):
nn = n*n
for i in count(1):
if n*i >= N: break
nums[n*i-1] += nn
print 'sig2(n) done - {} ms'.format((time()-init)*1000)
我用不同的值尝试了它,并且numpy非常令人失望。
for 2000:
sig2(n) done - 4.85897064209 ms
took : 33.7610244751 ms
using numpy
sig2(n) done - 31.5930843353 ms
took : 55.6900501251 ms
表示200000:
sig2(n) done - 1113.80600929 ms
took : 1272.8869915 ms
using numpy
sig2(n) done - 4469.48194504 ms
took : 4705.97100258 ms
它继续,我的代码不是真正的可扩展 - 因为它不是O(n),但有了这两个,除了这两个结果使用numpy导致性能问题。不应该比python列表和dicts更快?那是我对numpy的印象。
答案 0 :(得分:5)
正如@unutbu所说,当你使用矢量化操作时,numpy真的很闪耀。这是使用numpy的优化实现(它与Mathworld中除数函数的定义一致):
import numpy as np
def sig2_numpy(N):
x = np.arange(1,N+1)
x[(N % x) != 0] = 0
return np.sum(x**2)
当你打电话时,速度要快得多:
>> import time
>> init = time.time()
>> print sig2_numpy(20000)
>> print "It took", (time.time()-init)*1000., 'ms'
It took 0.916957855225 ms
答案 1 :(得分:3)
NumPy通过对整个数组执行计算而不是一次对单个值进行计算来实现速度。
写作时
for i in count(1):
if n*i >= N: break
nums[n*i-1] += nn
您正在强制NumPy数组nums
一次增加一个索引的数组中的单个值。这对于NumPy数组而言是一个缓慢的操作。