python - Numpy와 Matlab 어레이 합산 속도 비교




arrays performance (2)

inplace 작업에 적합한 동일한 변수를 업데이트하므로 다음과 같이 함수를 업데이트 할 수 있습니다.

def array_sum2(array_size, iterations):
    s = np.zeros((array_size, array_size))
    r = np.random.randn(array_size, array_size)
    for m in range(iterations):
        s /= 2
        s += r
    return s

이것은 array_sum 비해 내 컴퓨터에서 다음과 같은 속도의 이점을 제공합니다

run time: 157.32 ms
run time2: 672.43 ms

나는 최근에 Numpy와 함께 MATLAB 스크립트를 Python으로 변환했으며 속도가 상당히 느려지는 것을 발견했습니다. 나는 비슷한 성능을 기대했기 때문에 내가 뭔가 잘못하고 있는지 궁금해.

아래 예제처럼 필자는 수동으로 기하 급수를 합산했다.

MATLAB 버전 :

function s = array_sum(a, array_size, iterations)
    s = zeros(array_size);
    for m = 1:iterations
        s = a + 0.5*s;
    end
end

% benchmark code
array_size = 500
iterations = 500
a = randn(array_size)
f = @() array_sum(a, array_size, iterations);
fprintf('run time: %.2f ms\n', timeit(f)*1e3);

파이썬 / 누피 버전 :

import numpy as np
import timeit

def array_sum(a, array_size, iterations):
    s = np.zeros((array_size, array_size))
    for m in range(iterations):
        s = a + 0.5*s
    return s

array_size = 500
iterations = 500
a = np.random.randn(array_size, array_size)
timeit_iterations = 10
t1 = timeit.timeit(lambda: array_sum(a, array_size, iterations),
                   number=timeit_iterations)
print("run time: {:.2f} ms".format(1e3*t1/timeit_iterations))

내 컴퓨터에서 MATLAB은 58ms 이내에 완료됩니다. Python 버전은 292ms 또는 5X 느리게 실행됩니다.

또한 Numba JIT 데코레이터 @jit('f8[:,:](i8, i8)', nopython=True) 를 추가하여 파이썬 코드의 속도를 높이려고했지만 시간은 @jit('f8[:,:](i8, i8)', nopython=True) (4X 느림)로 떨어졌습니다.

이것은 예상보다 느립니다. 부적절하게 timeit을 사용하고 있습니까? 파이썬 코드에 문제가 있습니까?

편집 : 임의의 행렬이 벤치 마크 된 함수 외부에서 생성되도록 편집.

편집 2 : Numpy 대신 Torch를 사용하여 벤치 마크를 실행했습니다 ( s = torch.add(s, 0.5, a) 로 합계를 계산 s = torch.add(s, 0.5, a) ). 내 컴퓨터에서 단지 s = torch.add(s, 0.5, a) 만 실행됩니다!


내 경험에 비추어 볼 때 numba의 jit 함수를 사용하면 일반적으로 배열 연산을 루프확장하는 것이 더 빠릅니다. 그래서 파이썬 함수를 다음과 같이 재 작성하려고했습니다 :

@jit(nopython=True, cache=True)
def array_sum_numba(a, array_size, iterations):
    s = np.zeros((array_size, array_size))
    for m in range(iterations):
        for i in range(array_size):
            for j in range(array_size):
                s[i,j] = a[i,j] + 0.5 * s[i,j]
    return s

그리고 호기심에서 나는 매개 변수에 약간의 수정을 가하여 @ percusse의 버전을 테스트했습니다.

def array_sum2(r, array_size, iterations):
    s = np.zeros((array_size, array_size))
    for m in range(iterations):
        s /= 2
        s += r
    return s

내 컴퓨터의 테스트 결과는 다음과 같습니다.

  • 원래 버전 런타임 : 143.83 ms
  • 루프 버전 실행 시간 : 26.99 ms
  • @ percusse의 버전 실행 시간 : 61.38 ms

이 결과는 내 예상 내에 있습니다. timeup 반복을 50으로 늘려 numba 버전에 상당한 시간 단축을 가져 왔음을 언급 할 가치가 있습니다.

요약하면 : numba의 jit를 사용하고 루프에서 함수를 작성하면 Python 코드가 크게 가속 될 수 있습니다. 내 컴퓨터에 Matlab을 테스트 할 필요는 없지만 파이썬 버전이 더 빠르다고 생각합니다.





numpy