(python) 파일 배포, python with C
파일 배포
보통 pyinstaller
로 .exe를 만든 다음 배포한다.
python에서 C를 사용하는 방법
속도 향상을 위해 pypy를 고려하는 경우도 있는데, pre-JIT가 느린건 그렇다 치더라도 native python으로만 구현해야 동작을 보장할 수 있다는 절대적인 단점이 있다. C extension을 사용하는 다른 라이브러리를 사용하는 경우 pypy가 제대로 동작함을 보장할 수 없다. 어느 경우든 C running time은 동일하다고 봐도 된다. 간단하게 사용할 때는 ctypes를, 규모있는 라이브러리를 사용할 때는 C extension을( 아마 텐서플로우도 이렇게 만들지 않았을까 싶다. 텐서플로우는 Core에 C++을 사용한다. ) 사용하면 된다.
Cython
cython은 python의 superset이다. cython으로 코딩하면 python과 C를 모두 사용할 수 있다. 배우기 귀찮다는 점만 제외하면 Cython은 extension 작성하는 것 보다 쉽고, ctypes보다 빠르다. 위 두가지가 python은 인터프리터에서 돌아가고 C library를 호출할 때만 C로 넘어가는 반면 Cython은 애초에 코드 전체를 컴파일하게 된다. 아나콘다에 cython 컴파일러가 포함되어 있다.
1
2
python setup.py [build\_ext --inplace]
이런식으로 컴파일한다. build_ext 옵션은 .pyx를 찾아 .so로 만드는 옵션, –inplace 옵션은 현재 디렉토리에 생성하는 옵션.
tip
1) cython -a filename.pyx
html 형식의 보고서를 생성할 수 있다. c code로 변환된 python code를 line 단위로 볼 수 있으며, 파이썬 코드와 c 코드가 어느 비율로 실행되는지, 병목은 어디서 생기는지를 프로파일링 하기 좋다. 이 때 프로파일링에 line_profiler도 같이 사용하면 좋다.
2) memory view [:]
3) prange와 -fopenmp
ctype : C로 작성된 공유 라이브러리 호출
http://hashcode.co.kr/questions/243/python%EC%97%90%EC%84%9C-cc%EB%B6%80%EB%A5%B4%EA%B8%B0
https://docs.python.org/3/library/ctypes.html
일반적으로 C extension보다 ctypes를 추천한다. 함수 호출 횟수가 적은 경우는 ctypes와 C extension의 성능 차이가 미미하다. ctypes는 바로바로 파이썬 코드에 적용할 수 있기 때문에 쉽고 빠르게 사용할 수 있다. 또한 ctypes는 소스코드 없이 라이브러리만 있어도 사용 가능하다.
ctypes의 단점은 C library를 호출하는데 또다른 python code가 들어가므로, 반복문 안에서 C library를 호출하는 등 호출이 잦은 경우는 적절하지 않다는 점이다. 그러나 이는 C code와 python code의 역할을 나눌 때 C library의 호출 횟수를 줄이도록 하면 해결할 수 있다.
C extension
https://docs.python.org/3/extending/extending.html
C extension 방법은 wrapper 함수를 새로 작성해야 해서 꽤나 오래걸리고 귀찮은 작업이다. 확장성도 떨어진다.
- C 함수를 작성한다.
- C 함수를 wrapping하는 wrapper 함수를 작성한다. wrapper함수는 보통 다음과 같이 동작한다. a) 파이썬 데이터 타입을 C 데이터 타입으로 변경한다. : int PyArg_ParseTuple() b) C 함수를 호출한다. c) 결과를 C 데이터 타입에서 파이썬 데이터 타입으로 변경하고 리턴한다. : PyObject* Py_BuildValue()
- 함수를 PyMethodDef ModuleMethods[] 배열에 추가한다.
- 모듈 초기화 함수인 void initModule()을 추가한다.
- 컴파일한다. a) setup.py 생성 b) python setup.py build 명령으로 빌드한다. 공유 라이브러리(.dll 또는 .so)가 생성된다. c) python setup.py install 명령으로 모듈을 설치한다.
- import해서 사용한다.
이 방법도 ctypes처럼 공유 라이브러리를 사용하게 된다. 의문은 어차피 라이브러리로 호출하게 되는건 똑같은데 왜 ctypes가 더 느리냐는 것이다. 추측은 이렇다. C extension 방식은 단순히 wrapper 함수를 호출하면 알아서 처리해준 다음 파이썬 데이터 타입으로 리턴해주는데, ctypes는 wapper가 하는 a), b), c)를 직접 처리해야 해서 느린 것 같다.