在Python中,理论上,哪个方法应该更快test1
和test2
(假设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)
答案 0 :(得分:7)
在Python的任何实现中,时间将绝大多数由两个向量的乘法控制,每个向量具有100,000个元素。与此相比,其他一切都是噪音。如果你真的对测量其他开销很感兴趣,那么使矢量小得多。
在CPython中,test2()
很可能会更快一点。它有一个“额外”参数,但是参数是以“C速度”解压缩的,所以这并不重要。通过LOAD_FAST
操作码访问参数的方式与局部变量相同,这是一种简单的array[index]
访问。
在test1()
中,self.x
的每个实例都会在字典self.__dict__
中查找字符串“x”。这比索引数组访问慢。但与冗长的乘法所花费的时间相比,它基本上没什么。
答案 1 :(得分:1)
我知道这一点错过了问题的重点,但是既然你用numpy
标记问题并且正在考虑大型阵列的速度差异,我想我会提到有更快的解决方案完全不同的东西。
所以,你正在做的是一个点积,所以使用numpy.dot
,它是通过外部库(LAPACK?)的乘法和求和构建的(为方便起见,我将使用语法虽然@Tim的回答是test1
,但因为不需要传递额外的论据。)
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