2

在 Python 中,从理论上讲,哪种方法应该更快test1test2假设 的值相同x)。我尝试过使用%timeit,但几乎没有什么区别。

import numpy as np

class Tester():

    def __init__(self):
        self.x = np.arange(100000)

    def test1(self):
        return np.sum(self.x * self.x )

    def test2(self,x):
        return np.sum(x*x)
4

2 回答 2

7

在 Python 的任何实现中,时间将主要由两个向量相乘,每个向量有 100,000 个元素。与此相比,其他一切都是噪音。如果您真的对测量其他开销感兴趣,请使向量更小。

在 CPython 中,test2()很可能会快一点。它有一个“额外的”参数,但参数是“以 C 速度”解包的,所以这并不重要。通过操作码访问参数的方式与访问局部变量的方式相同LOAD_FAST,这是一种简单的array[index]访问方式。

test1()中,每个 的实例self.x都会在字典中查找字符串“x” self.__dict__。这比索引数组访问慢。但与长篇大论的乘法所花费的时间相比,基本上算不了什么。

于 2013-11-03T22:05:27.387 回答
1

我知道这种方式没有抓住问题的重点,但是由于您用标签标记了问题numpy并正在查看大型阵列的速度差异,我想我会提到有更快的解决方案完全是另一回事。

所以,你正在做的是一个点积,所以 use numpy.dot,它是用外部库(LAPACK?)的乘法和求和构建的(为了方便起见,我将使用 的语法test1,尽管@Tim's answer,因为不需要传递额外的参数。)

def test3(self):
    return np.dot(self.x, self.x)

甚至可能更快(当然更通用):

def test4(self):
    return np.einsum('i,i->', self.x, self.x)

以下是一些测试:

In [363]: paste
class Tester():
    def __init__(self, n):
        self.x = np.arange(n)
    def test1(self):
        return np.sum(self.x * self.x)
    def test2(self, x):
        return np.sum(x*x)
    def test3(self):
        return np.dot(self.x, self.x)
    def test4(self):
        return np.einsum('i,i->', self.x, self.x)
## -- End pasted text --

In [364]: t = Tester(10000)

In [365]: np.allclose(t.test1(), [t.test2(t.x), t.test3(), t.test4()])
Out[365]: True

In [366]: timeit t.test1()
10000 loops, best of 3: 37.4 µs per loop

In [367]: timeit t.test2(t.x)
10000 loops, best of 3: 37.4 µs per loop

In [368]: timeit t.test3()
100000 loops, best of 3: 15.2 µs per loop

In [369]: timeit t.test4()
100000 loops, best of 3: 16.5 µs per loop

In [370]: t = Tester(10)

In [371]: timeit t.test1()
100000 loops, best of 3: 16.6 µs per loop

In [372]: timeit t.test2(t.x)
100000 loops, best of 3: 16.5 µs per loop

In [373]: timeit t.test3()
100000 loops, best of 3: 3.14 µs per loop

In [374]: timeit t.test4()
100000 loops, best of 3: 6.26 µs per loop

谈到小的,几乎是语法上的速度差异,考虑使用一种方法而不是独立函数:

def test1b(self):
    return (self.x*self.x).sum()

给出:

In [385]: t = Tester(10000)

In [386]: timeit t.test1()
10000 loops, best of 3: 40.6 µs per loop

In [387]: timeit t.test1b()
10000 loops, best of 3: 37.3 µs per loop

In [388]: t = Tester(3)

In [389]: timeit t.test1()
100000 loops, best of 3: 16.6 µs per loop

In [390]: timeit t.test1b()
100000 loops, best of 3: 14.2 µs per loop
于 2013-11-04T23:45:15.377 回答