Search
Duplicate

Numpy Optimization and Parallelization

Created
5/28/2021, 10:22:00 AM
Tags
Empty

1. 문제상황

[100000, 1000] 크기의 matrix를 10만차원 축으로 cumsum을 했더니 약 2.3초가 걸려서 이를 더 빠르게 하고싶음.
기본 실험: 해당 matrix에 대해서 np.sum과 np.cumsum 을 수행해봄. 3번과 4번 cell에서는 cumsum을 한번에 모든 dim에대해 한것과 하나씩 바꿔가면서 한 실험 결과임cumsum의 경우 메모리에 writing하는 연산이 많아 sum보다 많이 느림.그런데 3번과 4번에서 속도차이가 나는 것이 이상해서, inplace cumsum으로 바꾸니 속도가 동일해짐.

2. C로 최적화?

여기서 더 빠르게 하기 위해, Numpy를 C로바꾸면 더 빨라질까? 결론은 Numpy가 C보다 더 빠르다,.
Python VS Chttps://medium.com/coding-with-clarity/speeding-up-python-and-numpy-c-ing-the-way-3b9658ed78f4위 블로그에서는 Python / C / Numpy의 속도비교를 matrix의 크기에따라 바꿔가면서 수행함.Matrix크기가 작을 때, Numpy는 python 기본 for문보다 느리고, C++ for 문보다는 훨씬 느림
그런데 Matrix크기가 매우 커지기 시작하면, Numpy가 C++보다 빨라짐.
이것이 가능한 이유는 numpy가 거대한 matrix의 연산에 최적으로 구현된 c기반의 라이브러리이기 때문임.(C로 컴파일된 함수를 내부적으로 실행함)

여러가지 다양한 Python최적화 라이브러리

조금 사용이 복잡하지만, Pure C++에 거의 가까운 속도를 내는 python 라이브러리가 있음.

3. 보다 강력한 방법

기본적으로 Numpy는 특정 몇개의 api(np.dot 등)에 대해서만 BLAS를 이용한 백앤드 parallelization이 구현되어있음. 그 이외의 대부분의 operation은 병렬화가 전혀안되고 싱글코어로 작동함.
결론: CPU 병렬화 or GPU 병렬화

CPU 병렬화

1.
Numpy를 지우고 OpenBlas를 백앤드로 사용하도록 재설치 https://roman-kh.github.io/numpy-multicore/
sharedmem을 쓰면 더 빨라짐.(그런데 numpy는 이게 내부적으로 이미 구현되었다는 듯함) https://ask.sagemath.org/question/36437/how-to-efficiently-calculate-a-sum-of-arrays-with-numpy-and-parallel-decorator/
1.
Ipyparallel: Ipython에서 cell을 자동으로 병렬화시켜 실행해주는 라이브러리 https://ipyparallel.readthedocs.io/en/latest/magics.html
2.
Numba + Parallel : python code를 JIT 컴파일하여 native machine instruction(C level)으로 실행시켜주는 라이브러리. 이 Numba에다가 Python Multiprocessing 라이브러리를 결합하면 Python에서 C레벨의 병렬화가 가능함. https://roman-kh.github.io/numba-1/https://roman-kh.github.io/numba-2/https://numba.pydata.org

GPU 병렬화(전처리 컴퓨터에 GPU가 있어야만 가능함)

3.
머신러닝용 GPU서버에서 pytorch 등으로 전처리 layer를 모델에 포함시켜서 구현
5.
CuPy: NumPy by CUDA https://cupy.chainer.org/

4. 공부하면서 알게된 내용

Python에서 decorator를 이용하면 손쉽게 특정 함수를 병렬로 실행시킬 수 있음 https://stackoverflow.com/questions/11731664/python-making-a-class-method-decorator-that-returns-a-method-of-the-same-class
그냥 cumsum보다 inplace cumsum이 훨씬 빠르다.
Ipython에서 %%time을 쓰면 손쉽게 cell의 실행 시간을 알 수 있음
systime은 시스템의 커널 함수 호출시간, usertime은 유저의 코드에서 걸리는 시간.
Python은 Global Interpreter Lock 때문에 오직 1개의 thread만 돌아갈 수 있음. 그래서 이를 해결하려면 multiprocessing을 사용해야함.
TOP