fod*_*don 65 python performance numpy
要求:
这是我的代码:
def __init__(self):
self.data = []
def update(self, row):
self.data.append(row)
def finalize(self):
dx = np.array(self.data)
Run Code Online (Sandbox Code Playgroud)
我试过的其他事情包括以下代码......但这是waaaaay慢.
def class A:
def __init__(self):
self.data = np.array([])
def update(self, row):
np.append(self.data, row)
def finalize(self):
dx = np.reshape(self.data, size=(self.data.shape[0]/5, 5))
Run Code Online (Sandbox Code Playgroud)
以下是如何调用此示意图的示意图:
for i in range(500000):
ax = A()
for j in range(200):
ax.update([1,2,3,4,5])
ax.finalize()
# some processing on ax
Run Code Online (Sandbox Code Playgroud)
Owe*_*wen 77
我尝试了几个不同的东西,时间.
import numpy as np
Run Code Online (Sandbox Code Playgroud)
你提到的方法很慢:(32.094秒)
class A:
def __init__(self):
self.data = np.array([])
def update(self, row):
self.data = np.append(self.data, row)
def finalize(self):
return np.reshape(self.data, newshape=(self.data.shape[0]/5, 5))
Run Code Online (Sandbox Code Playgroud)常规ol Python列表:(0.308秒)
class B:
def __init__(self):
self.data = []
def update(self, row):
for r in row:
self.data.append(r)
def finalize(self):
return np.reshape(self.data, newshape=(len(self.data)/5, 5))
Run Code Online (Sandbox Code Playgroud)试图在numpy中实现一个arraylist:(0.362秒)
class C:
def __init__(self):
self.data = np.zeros((100,))
self.capacity = 100
self.size = 0
def update(self, row):
for r in row:
self.add(r)
def add(self, x):
if self.size == self.capacity:
self.capacity *= 4
newdata = np.zeros((self.capacity,))
newdata[:self.size] = self.data
self.data = newdata
self.data[self.size] = x
self.size += 1
def finalize(self):
data = self.data[:self.size]
return np.reshape(data, newshape=(len(data)/5, 5))
Run Code Online (Sandbox Code Playgroud)这就是我计时的方式:
x = C()
for i in xrange(100000):
x.update([i])
Run Code Online (Sandbox Code Playgroud)
所以看起来普通的旧Python列表非常好;)
Pra*_*mar 11
使用欧文的帖子中的类声明,这是一个修订的时间,具有最终化的一些效果.
简而言之,我发现C类提供的实现速度比原始帖子中的方法快60多倍.(为文本墙道歉)
我用过的文件:
#!/usr/bin/python
import cProfile
import numpy as np
# ... class declarations here ...
def test_class(f):
x = f()
for i in xrange(100000):
x.update([i])
for i in xrange(1000):
x.finalize()
for x in 'ABC':
cProfile.run('test_class(%s)' % x)
Run Code Online (Sandbox Code Playgroud)
现在,由此产生的时间:
903005 function calls in 16.049 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 16.049 16.049 <string>:1(<module>)
100000 0.139 0.000 1.888 0.000 fromnumeric.py:1043(ravel)
1000 0.001 0.000 0.003 0.000 fromnumeric.py:107(reshape)
100000 0.322 0.000 14.424 0.000 function_base.py:3466(append)
100000 0.102 0.000 1.623 0.000 numeric.py:216(asarray)
100000 0.121 0.000 0.298 0.000 numeric.py:286(asanyarray)
1000 0.002 0.000 0.004 0.000 test.py:12(finalize)
1 0.146 0.146 16.049 16.049 test.py:50(test_class)
1 0.000 0.000 0.000 0.000 test.py:6(__init__)
100000 1.475 0.000 15.899 0.000 test.py:9(update)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
100000 0.126 0.000 0.126 0.000 {method 'ravel' of 'numpy.ndarray' objects}
1000 0.002 0.000 0.002 0.000 {method 'reshape' of 'numpy.ndarray' objects}
200001 1.698 0.000 1.698 0.000 {numpy.core.multiarray.array}
100000 11.915 0.000 11.915 0.000 {numpy.core.multiarray.concatenate}
208004 function calls in 16.885 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 16.885 16.885 <string>:1(<module>)
1000 0.025 0.000 16.508 0.017 fromnumeric.py:107(reshape)
1000 0.013 0.000 16.483 0.016 fromnumeric.py:32(_wrapit)
1000 0.007 0.000 16.445 0.016 numeric.py:216(asarray)
1 0.000 0.000 0.000 0.000 test.py:16(__init__)
100000 0.068 0.000 0.080 0.000 test.py:19(update)
1000 0.012 0.000 16.520 0.017 test.py:23(finalize)
1 0.284 0.284 16.883 16.883 test.py:50(test_class)
1000 0.005 0.000 0.005 0.000 {getattr}
1000 0.001 0.000 0.001 0.000 {len}
100000 0.012 0.000 0.012 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1000 0.020 0.000 0.020 0.000 {method 'reshape' of 'numpy.ndarray' objects}
1000 16.438 0.016 16.438 0.016 {numpy.core.multiarray.array}
204010 function calls in 0.244 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.244 0.244 <string>:1(<module>)
1000 0.001 0.000 0.003 0.000 fromnumeric.py:107(reshape)
1 0.000 0.000 0.000 0.000 test.py:27(__init__)
100000 0.082 0.000 0.170 0.000 test.py:32(update)
100000 0.087 0.000 0.088 0.000 test.py:36(add)
1000 0.002 0.000 0.005 0.000 test.py:46(finalize)
1 0.068 0.068 0.243 0.243 test.py:50(test_class)
1000 0.000 0.000 0.000 0.000 {len}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1000 0.002 0.000 0.002 0.000 {method 'reshape' of 'numpy.ndarray' objects}
6 0.001 0.000 0.001 0.000 {numpy.core.multiarray.zeros}
Run Code Online (Sandbox Code Playgroud)
A类被更新破坏,B类被最终化破坏.C类在两者面前都很强大.
您用于完成的函数存在很大的性能差异。考虑以下代码:
N=100000
nruns=5
a=[]
for i in range(N):
a.append(np.zeros(1000))
print "start"
b=[]
for i in range(nruns):
s=time()
c=np.vstack(a)
b.append((time()-s))
print "Timing version vstack ",np.mean(b)
b=[]
for i in range(nruns):
s=time()
c1=np.reshape(a,(N,1000))
b.append((time()-s))
print "Timing version reshape ",np.mean(b)
b=[]
for i in range(nruns):
s=time()
c2=np.concatenate(a,axis=0).reshape(-1,1000)
b.append((time()-s))
print "Timing version concatenate ",np.mean(b)
print c.shape,c2.shape
assert (c==c2).all()
assert (c==c1).all()
Run Code Online (Sandbox Code Playgroud)
使用 concatenate 似乎比第一个版本快两倍,比第二个版本快 10 倍以上。
Timing version vstack 1.5774928093
Timing version reshape 9.67419199944
Timing version concatenate 0.669512557983
Run Code Online (Sandbox Code Playgroud)
添加到Owen和Prashant Kumar 的答案中,这里是一个使用多维 numpy 数组(又名形状)的版本,可以加速 numpy 解决方案的代码。如果您需要经常访问 ( finalize()) 数据,这尤其有用。
| 版本 | 普拉尚特·库马尔 | 行长度=1 | 行长度=5 |
|---|---|---|---|
| A 类 - np.append | 2.873秒 | 2.776秒 | 0.682秒 |
| B 类 - python 列表 | 6.693秒 | 80.868秒 | 22.012秒 |
| C类——数组列表 | 0.095秒 | 0.180秒 | 0.043秒 |
该专栏Prashant Kumar是他在我的机器上执行的示例,以进行比较。这row_length=5是最初问题的例子。,的急剧增加python list来自{built-in method numpy.array},这意味着 numpy 需要更多的时间将多维列表列表转换为相对于一维列表的数组,并在两者具有相同数字条目的情况下重塑它,例如np.array([[1,2,3]*5])与np.array([1]*15).reshape((-1,3))。
这是代码:
import cProfile
import numpy as np
class A:
def __init__(self,shape=(0,), dtype=float):
"""First item of shape is ingnored, the rest defines the shape"""
self.data = np.array([], dtype=dtype).reshape((0,*shape[1:]))
def update(self, row):
self.data = np.append(self.data, row)
def finalize(self):
return self.data
class B:
def __init__(self, shape=(0,), dtype=float):
"""First item of shape is ingnored, the rest defines the shape"""
self.shape = shape
self.dtype = dtype
self.data = []
def update(self, row):
self.data.append(row)
def finalize(self):
return np.array(self.data, dtype=self.dtype).reshape((-1, *self.shape[1:]))
class C:
def __init__(self, shape=(0,), dtype=float):
"""First item of shape is ingnored, the rest defines the shape"""
self.shape = shape
self.data = np.zeros((100,*shape[1:]),dtype=dtype)
self.capacity = 100
self.size = 0
def update(self, x):
if self.size == self.capacity:
self.capacity *= 4
newdata = np.zeros((self.capacity,*self.data.shape[1:]))
newdata[:self.size] = self.data
self.data = newdata
self.data[self.size] = x
self.size += 1
def finalize(self):
return self.data[:self.size]
def test_class(f):
row_length = 5
x = f(shape=(0,row_length))
for i in range(int(100000/row_length)):
x.update([i]*row_length)
for i in range(1000):
x.finalize()
for x in 'ABC':
cProfile.run('test_class(%s)' % x)
Run Code Online (Sandbox Code Playgroud)
还有另一个选项可以添加到Luca Fiaschi 的上述帖子中。
b=[]
for i in range(nruns):
s=time.time()
c1=np.array(a, dtype=int).reshape((N,1000))
b.append((time.time()-s))
print("Timing version array.reshape ",np.mean(b))
Run Code Online (Sandbox Code Playgroud)
我的计时结果是:
Timing version vstack 0.6863266944885253
Timing version reshape 0.505419111251831
Timing version array.reshape 0.5052066326141358
Timing version concatenate 0.5339600563049316
Run Code Online (Sandbox Code Playgroud)