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 C
https://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 라이브러리가 있음.
http://scipy-cookbook.readthedocs.io/items/PerformancePython.html
3. 보다 강력한 방법
- 기본적으로 Numpy는 특정 몇개의 api(np.dot 등)에 대해서만 BLAS를 이용한 백앤드 parallelization이 구현되어있음. 그 이외의 대부분의 operation은 병렬화가 전혀안되고 싱글코어로 작동함.
- 결론: CPU 병렬화 or GPU 병렬화
CPU 병렬화
- Numpy를 지우고 OpenBlas를 백앤드로 사용하도록 재설치 https://roman-kh.github.io/numpy-multicore/
- Numexpr http://www.bitsofbits.com/2014/09/21/numpy-micro-optimization-and-numexpr/
- Python의 multiprocessing 라이브러리를 이용한 구현 https://docs.python.org/3/library/multiprocessing.htmlhttp://scipy-cookbook.readthedocs.io/items/ParallelProgramming.html
- sharedmem을 쓰면 더 빨라짐.(그런데 numpy는 이게 내부적으로 이미 구현되었다는 듯함) https://ask.sagemath.org/question/36437/how-to-efficiently-calculate-a-sum-of-arrays-with-numpy-and-parallel-decorator/
- Ipyparallel: Ipython에서 cell을 자동으로 병렬화시켜 실행해주는 라이브러리 https://ipyparallel.readthedocs.io/en/latest/magics.html
- 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가 있어야만 가능함)
- CUDA python using Numba https://developer.nvidia.com/how-to-cuda-python
- PyCUDA https://developer.nvidia.com/pycuda
- 머신러닝용 GPU서버에서 pytorch 등으로 전처리 layer를 모델에 포함시켜서 구현
- 기타 여러 병렬화 라이브러리 https://www.scipy.org/topical-software.html#parallel-and-distributed-programming
- 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을 사용해야함.
- 종합적인 방법들: https://www.quora.com/What-are-the-ways-for-parallelizing-Python-and-NumPy-codes
'A. Development > for Machine Learning' 카테고리의 다른 글
Pytorch 개발 팁 (0) | 2020.01.16 |
---|---|
Pandas (0) | 2018.06.29 |
Numpy 문법, API, 환경설정 / HDF5를 위한 H5PY API (0) | 2015.12.01 |
댓글