对于大型数组而言比列表慢得多?

时间:2012-11-14 10:23:04

标签: python numpy

检查我的以下代码;它是在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的印象。

2 个答案:

答案 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数组而言是一个缓慢的操作。