고성능 파이썬에 numpy를 소개하고 제 컴퓨터에서 코드를 사용하여 장을 읽었습니다. 실수로 for 루프를 사용하여 numpy 버전을 실행하고 결과가 원래 파이썬 루프에 비해 놀라 울 정도로 느리다는 것을 알았습니다.원시 파이썬 목록에서 for 루프가 numpy 배열의 루프보다 빠릅니다.
코드의 간략화 된 버전 I이 1과 0의 2 차원 어레이의 X 및 다른 2D 배열 Y를 정의하는 경우, 다음 다음 반복 개념적 X + = Y.
import time
import numpy as np
grid_shape = (1024, 1024)
def simple_loop_comparison():
xmax, ymax = grid_shape
py_grid = [[0]*ymax for x in range(xmax)]
py_ones = [[1]*ymax for x in range(xmax)]
np_grid = np.zeros(grid_shape)
np_ones = np.ones(grid_shape)
def add_with_loop(grid, add_grid, xmax, ymax):
for x in range(xmax):
for y in range(ymax):
grid[x][y] += add_grid[x][y]
repeat = 20
start = time.time()
for i in range(repeat):
# native python: loop over 2D array
add_with_loop(py_grid, py_ones, xmax, ymax)
print('for loop with native list=', time.time()-start)
start = time.time()
for i in range(repeat):
# numpy: loop over 2D array
add_with_loop(np_grid, np_ones, xmax, ymax)
print('for loop with numpy array=', time.time()-start)
start = time.time()
for i in range(repeat):
# vectorized numpy operation
np_grid += np_ones
print('numpy vectorization=', time.time()-start)
if __name__ == "__main__":
simple_loop_comparison()
X로 Y를 추가로 인 나는 완전히 NumPy와 벡터화 작업이 다른 두를 능가하지만 기본 파이썬 목록보다 훨씬 느린 NumPy와 배열 결과에 대한 루프를 위해 사용하는 것을보고 놀랐다 것으로 기대
# when repeat=10
for loop with native list= 2.545672655105591
for loop with numpy array= 11.622980833053589
numpy vectorization= 0.020279645919799805
# when repeat=20
for loop with native list= 5.195128440856934
for loop with numpy array= 23.241904258728027
numpy vectorization= 0.04613637924194336
: 같은
결과는 보인다. 나의 이해는 최소한 캐시가 numpy 배열로 상대적으로 채워 져야만한다는 것이다. for 루프를 사용하더라도 벡터화 없이는 성능이 뛰어나다.
numpy 또는 CPU/캐시/메모리가 저급 수준에서 작동하지 않는 이유가 있습니까? 고맙습니다.
편집 : 변경 제목
이 아니다 'numpy' 루프 있지만 'numpy' 배열을 가진 보통의 파이썬 루프. – Sraw
제목을 편집했습니다. 그것이 무엇이든 그것을 부르기 원한다면, 질문은 왜 성능 격차가 존재 하는가입니다. – dhu
세 가지 : 1.) 이중 색인 : 기존 목록 및 요소를 참조하는 목록의 목록에 대해 2 차원 배열의 경우 행 및 요소에 대한 새 개체를 만듭니다. 2.) numpy'__getitem __/__ setitem__'은 목록 카운터 부분보다 더 많은 인자를 처리합니다. 3.) (나는 그 차이점을 완전히 이해하지는 못했지만 목록에 있습니다.) list .'__getitem__'는 내장 된 배열입니다. '__getitem__'은 메소드 랩퍼입니다 –