요구 사항 :
- 데이터에서 임의로 큰 배열을 확장해야합니다.
- 배열이 매번 맞을 것이라는 보장없이 크기 (대략 100-200)를 추측 할 수 있습니다.
- 최종 크기로 커지면 숫자 계산을 수행해야하므로 결국에는 2 차원 numpy 배열을 선호합니다.
- 속도가 중요합니다. 예를 들어, 300 개 파일 중 하나에 대해 update () 메서드는 4,500 만 번 호출되고 (150 초 정도 소요) finalize () 메서드는 50 만 번 호출됩니다 (총 106 초 소요) … 총 250 초 소요 정도.
내 코드는 다음과 같습니다.
def __init__(self):
self.data = []
def update(self, row):
self.data.append(row)
def finalize(self):
dx = np.array(self.data)
내가 시도한 다른 것들은 다음 코드를 포함하지만 … 이것은 속도가 느립니다.
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))
이것이 어떻게 호출되는지에 대한 회로도는 다음과 같습니다.
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
답변
타이밍과 함께 몇 가지 다른 것을 시도했습니다.
import numpy as np
-
느리다고 언급 한 방법 : (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))
-
일반 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))
-
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))
그리고 이것이 내가 시간을 정한 방법입니다.
x = C()
for i in xrange(100000):
x.update([i])
따라서 일반적인 오래된 Python 목록이 꽤 좋은 것 같습니다.)
답변
np.append ()는 매번 배열의 모든 데이터를 복사하지만 목록은 용량 (1.125)을 늘립니다. 목록은 빠르지 만 메모리 사용량은 배열보다 큽니다. 메모리에 관심이 있다면 파이썬 표준 라이브러리의 배열 모듈을 사용할 수 있습니다.
이 주제에 대한 토론은 다음과 같습니다.
답변
Owen의 게시물에있는 클래스 선언을 사용하여 마무리 효과가있는 수정 된 타이밍이 있습니다.
요컨대, 나는 원래 포스트의 방법보다 60 배 이상 빠른 구현을 제공하는 클래스 C를 발견했습니다. (텍스트 벽에 대한 사과)
내가 사용한 파일 :
#!/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)
이제 결과 타이밍 :
ㅏ:
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}
클래스 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()
concatenate를 사용하는 것은 첫 번째 버전보다 두 배 빠르며 두 번째 버전보다 10 배 이상 빠릅니다.
Timing version vstack 1.5774928093
Timing version reshape 9.67419199944
Timing version concatenate 0.669512557983
답변
목록 작업으로 성능을 향상 시키려면 blist 라이브러리를 살펴보십시오. 파이썬 목록 및 기타 구조의 최적화 된 구현입니다.
나는 그것을 아직 벤치마킹하지 않았지만 그들의 페이지의 결과는 유망 해 보입니다.