【问题标题】:for huge arrays is numpy slower than list? [duplicate]对于巨大的数组来说,numpy 比 list 慢吗? [复制]
【发布时间】:2012-11-02 20:09:15
【问题描述】:

检查我的以下代码;它是在 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 非常令人失望。

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 会导致性能问题。 numpy 不应该比 python 列表和字典更快吗?这就是我对 numpy 的印象。

【问题讨论】:

  • 我看不到你的函数是如何实现除数函数的。返回值是多少?
  • 它返回 sigma_2 匹配给定条件的数字列表。这里只有一小部分代码...

标签: python numpy


【解决方案1】:

正如@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

【讨论】:

  • 请不要使用 &lt;&gt; 运算符,至少从 Python 2.0 (2000) 开始,它就被“认为已过时”。我已将其替换为 !=
  • @larsmans 我不知道。谢谢!
  • 哦,顺便说一句,np.sum(x**2) == np.dot(x,x)。后者可能更快,因为它不会产生中间的 x**2 数组。
  • 是的,你是对的 %timeit np.sum(x**2) -&gt; 8.88 ms per loop vs %timeit np.dot(x,x) -&gt; 1.78 ms per loop(对于 1e6 元素)。我将保留原样,因为这样可能更容易理解发生了什么。
【解决方案2】:

NumPy 通过对整个数组执行计算来提高速度,而不是一次对单个值进行计算。

当你写作时

    for i in count(1):
        if n*i >= N: break
        nums[n*i-1] += nn

您正在强制 NumPy 数组 nums 一次将数组中的单个值递增一个索引。对于 NumPy 数组,这是一个缓慢的操作。

【讨论】:

  • 对于那部分,如果我使用 numpy 生成另一个值为 0 的数组,如果索引不能被 n 和 n*n 整除,则 n 的倍数并执行数组加法运算,它会加速我的代码?
  • @thkang:正确答案:可能。更好的答案:试试看。
  • 看来@btel 已经实现了你所描述的。
猜你喜欢
  • 2018-11-12
  • 2012-06-16
  • 2011-03-14
  • 1970-01-01
  • 2012-01-13
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
  • 2017-11-26
相关资源
最近更新 更多