[Python] PyPy, Cython, CTypes 속도 비교 Develop Tip

파이썬으로 작업을 하다보면 특정 함수가 많이 느려
특정 함수의 속도를 빠르게 할 필요가 있습니다.

이럴 때에는 다음과 같은 것으로 튜닝을 할 수 있습니다.

pypy :
파이썬으로 만든 파이썬 JIT (Just-In-Time) 컴파일러 입니다.
처음에는 C가 아닌 파이썬으로 만든 것은 느려야 당연한데
어떻게 빠를까 의문이 가기는 했지만,
실제 테스트해 보니 정말 놀라운 결과가...

C-Extensions for Python 으로서
파이썬-like (선언부 등 몇가지를 제외하고)한 코드를
이용하여 파이썬에서 호출할 수 있는 쉐어드 라이브러리가 생성됩니다.
이를 파이썬에서 이용할 수 있습니다.

ctypes :
파이썬의 ctypes 를 이용하여 직접 쉐어드 라이브러리를 호출하는 것입니다.


이런 식으로 빠르게 해 볼 수 있는데요,

우선 다음코드를 확인해 봅니다.
(테스트는 같은 팀의 김진우 선임의 도움을 받았습니다)

아주 간단한 코드인데 바깥 loop를 십만번, 하부 loop를 만번 (곱하면 10억번) 돌면서
마지막인가를 체크하는 if 문이 있는 문장입니다.

위의 코드를 
$ time python loopcheck.py
명령으로 실행시간을 재 보았고,

또,

$ time pypy loopcheck.py
로 재 보았습니다.

그 다음 cython 을 설치한 다음
loopcheck.pyx 를 setup.py 로 만들어
cython 으로 돌렸습니다.

마지막으로 loopcheck.c 를 shared library 로 만든 다음

python에서 ctypetest.py 처럼 테스트 하였습니다.


그 결과는 놀라왔습니다.
(단위 : 초)

PyPy가 Cython 이나 심지어는 순수 C를 사용한 CTypes 이용한 것 보다도 더 빨랐습니다.
(제 맥북프로에서도 유사한 결과가 나오더군요)

만약 PyPy가 대부분의 다른 코드에서도 C와 유사한 속도가 나온다면 정말이지 
그동안 파이썬의 최대 단점으로 지적되었던 속도를 해결할 수 있지 않을까 싶습니다.

 또 흥미로운 것이 있는데,
JITPY 라는 것이 있습니다.

Python 안에 pypy를 쓸 수 있는 것입니다.
적어도 20배 더 빨리 수행된다고 합니다...

기존의 특정 부분을 빨리 돌리고 싶으로 유용할 것 같습니다.

어느 분께는 도움이 되셨기를 ...

핑백

  • 지훈현서 : [Ubuntu 14.04] mariaDB 10 및 pypy 설치와 pypy용 pip 2016-09-20 11:28:20 #

    ... .04 인 경우 해당 코멘트를 빼고 14.04에 코멘트 '#'를 넣어주셔요) 2) pypy 설치 및 pypy용 pip 설치하여 패키지 설치해 보기 (pypy 와 cpython의 속도 비교 참고) $ cat install_pypy.sh sudo apt-get install pypy pypy-devcurl -O https:// ... more

  • 지훈현서 : [Python] Redis rq 를 이용한 간단한 비동기 작업 큐 2017-05-17 14:11:35 #

    ... 는 것입니다.파이썬이 For loop 이나 재귀호출 등이 C나 Pypy에 비하여 많게는 40~50배까지 느리기 때문에이렇게 붙였나 봅니다. (CPython, PyPy, ctypes 등 실행 비교 참조) 참고로 위와 같이 실행 함수는 별도 참조 모듈로 떼어 놓아야 합니다. 위의 함수를 enqueue에 놓았더니 worker가 참조하지 ... more

덧글

  • 퍼렁머리 2015/01/29 19:50 # 답글

    pypy는 간단한 성능측정코드를 최적화해 버려서 루프를 아예 안돌려버리는 걸지도요....
  • 지훈현서아빠 2015/01/29 20:01 #

    저 루프 안에 여러 계산 문장을 넣어도 비슷한 결과가 나오는 것으로 보아, Loop 자체를 생략하는 것 같지는 않더라구요~~
  • 死海文書 2015/01/29 20:25 # 답글

    예상 이상으로 pypy가 빠르네요...
  • 지나가는사람 2015/01/29 21:25 # 삭제 답글

    pypy
    천만번 반복이 1억번 반복보다 오래거리는 것은 무슨이유죠?

    천만번 반복 혹은 다른 부분에서 오류 있는거 아닌가요?
  • 지나가는사람 2015/01/29 21:27 # 삭제

    0.758 -> 0.0758이거나
    혹은
    다른 부분의 오류 아닌가요?
  • 긁적 2015/01/30 00:12 # 답글

    Pypy 만든 사람들 정말 무서운 것 같아요................
  • joon 2015/01/30 08:31 # 삭제 답글

    죄송합니다만 저 코드는 비교에 쓰기는 좀 무리가 있네요. 일단 Cython코드의 경우 함수 안에서 i와 j가 int로 정의가 되어 있지 않아서 loop에 Python 오버헤드가 걸려서 아주 느려집니다. Cython의 효과를 보려면 룹 안의 모든 변수 type을 정의해줘야 합니다.

    그리고 추가로 loop 안에서 Python 함수를 (여기선 print) 부르면 역시 Python overhead가 걸리 때문에 Cython의 속도 향상을 기대하기 어렵습니다.

    정확한 속도 비교를 위한 예가 아닌 것 같네요.

    제가 print를 빼고 (다른 더하기 빼기 연산을 넣은 상태로) 실험해본 결과,

    (i, j가 정의되지 않은 경우)
    %timeit loopcheck.loop(1000, 1000)
    10 loops, best of 3: 20.8 ms per loop

    (i, j가 int로 정의된 경우)
    %timeit loopcheck_typed.loop(1000, 1000)
    1000 loops, best of 3: 316 µs per loop

    같은 Cython이지만 엄청나게 차이가 납니다.

    gist에 예제 코드를 달아두었습니다.

    pypy가 안 깔려 있어서 실험은 안해보았지만 아마도 모든 변수들을 정의하고 Python call을 빼면 Cython이 더 느리진 않을 겁니다. 그래도 Python call이 들어간 loop을 써야 하는 경우라면 pypy가 엄청나게 빠르긴 하겠네요.
  • 지훈현서아빠 2015/01/30 09:11 # 답글

    네~ 좋은 지적 감사드립니다.
    하여간 PyPy 에 대해 다른 시각으로 바라보게 되었답니다.
    (Loop 자체의 시간비교는 절대적인 아니라고 생각하고 있습니다)
    감사합니다~ ^^
  • 제이 2015/01/30 10:56 # 삭제 답글

    Cython의 경우는 기존 python 코드를 재활용한다는 차원에서 보면 좋을 듯 하겠네요.
    현재 Python으로 작업된 경우에 조금 더 속도의 향상을 위해서라면 사용해도 좋을 듯 해보입니다.

    그래도 PyPy가 빠르긴 하네요...
  • 개팔자3x4 2015/04/22 20:44 # 삭제 답글

    언제 봐도 흥미롭네요
    잘보고 갑니다.
  • Time To Share 2016/01/06 00:37 # 답글

    항상 블로그 재미있게 보고있습니다~ ^^ 유용한 정보감사합니다~ㅎ
    cython, cffi, ctype, pyston, pypy, SWIG, boost.python...
    파이썬의 속도향상을 위해 수많은 프로젝트들이 진행중인데 얼른 최고의 솔루션이 나와서 싹~ 정리가 되었으면 좋겠네요~
  • 지훈현서아빠 2016/01/06 07:19 #

    어느 언어나 어느 솔루션이건 간에 은총알은 없는 것 같습니다.
    그것을 이용하는 사람들이 어떻게 잘 활용할 수 있는가에 더
    중점을 두어야 하지 않나 싶습니다.
    즉, 우선 현재 최신 상황을 잘 보고 있다가 현재로서 제일
    안정된 것을 가장 잘 활용하는 것이 최적의 해라 할 수 있지 않을까요?
  • baubiue 2018/03/17 14:07 # 삭제 답글

    안녕하세요 정말 제게 필요한 내용 잘보았습니다.

    혹시 jitpy 사용법을 알수있을까요?
  • 지훈현서아빠 2018/03/17 16:17 #

    제가 답을 드릴 만큼 jitpy를 많이 사용못해보았습니다.
    위의 예처럼 하시면 되지 않을까 싶습니다.
댓글 입력 영역

구글애드텍스트