Post

(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

http://cython.org/

http://docs.cython.org/

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 함수를 새로 작성해야 해서 꽤나 오래걸리고 귀찮은 작업이다. 확장성도 떨어진다.

  1. C 함수를 작성한다.
  2. C 함수를 wrapping하는 wrapper 함수를 작성한다. wrapper함수는 보통 다음과 같이 동작한다. a) 파이썬 데이터 타입을 C 데이터 타입으로 변경한다. : int PyArg_ParseTuple() b) C 함수를 호출한다. c) 결과를 C 데이터 타입에서 파이썬 데이터 타입으로 변경하고 리턴한다. : PyObject* Py_BuildValue()
  3. 함수를 PyMethodDef ModuleMethods[] 배열에 추가한다.
  4. 모듈 초기화 함수인 void initModule()을 추가한다.
  5. 컴파일한다. a) setup.py 생성 b) python setup.py build 명령으로 빌드한다. 공유 라이브러리(.dll 또는 .so)가 생성된다. c) python setup.py install 명령으로 모듈을 설치한다.
  6. import해서 사용한다.

이 방법도 ctypes처럼 공유 라이브러리를 사용하게 된다. 의문은 어차피 라이브러리로 호출하게 되는건 똑같은데 왜 ctypes가 더 느리냐는 것이다. 추측은 이렇다. C extension 방식은 단순히 wrapper 함수를 호출하면 알아서 처리해준 다음 파이썬 데이터 타입으로 리턴해주는데, ctypes는 wapper가 하는 a), b), c)를 직접 처리해야 해서 느린 것 같다.

This post is licensed under CC BY 4.0 by the author.