Cython [Python, pypy] by 바죠

Cython

사이썬(Cython)은 CPython 확장 모듈을 손쉽게 생성하도록 고안된 컴퓨터 언어이다. 

특별히, 컴파일러를 활용하는 컴퓨터 언어이다. 반면, 파이썬은 컴파일러를 활용하지 않는 인터프리터 언어이다. 

사이썬 컴퓨터 언어는 파이썬 컴퓨터 언어 보다 상위 개념의 컴퓨터 언어이다.

실제적으로는 C 언어 프로그램을 자동으로 만든다.  

그 다음 컴파일을 수행하고 순차적으로 실행하여 결국 실행 속도 향상을 얻어내는 것이다. 

파이썬 문법을 기반으로 C/C++ 루틴을 호출을 위한 외부 함수 인터페이스을 지원한다. 

또한, 실행 속도 향상을 위한 정적 형(static type) 지정 등이 파이썬 컴퓨터 언어에  추가된  컴퓨터 언어이다. 

이러한 특징은 파이썬의 빠른 생산성을 유지하면서도 외부 C 라이브러리와 간결하게 연동하거나 실행 속도 향상 할 수 있도록 해준다.

파이썬은 실행 속도가 매우 느린 단점이 있다. 파이썬 언어는 C 언어 기준으로 약 100배 정도 느린 실행 속도를 가지고 있다.

파이썬: 동적 프로그래밍 언어 특성, 실시간 코드 해석 특성

사이썬은 파이썬 스크립트를 C언어로 작성된 프로그램을 만든다. 

동시에 해당 C 프로그램을 컴파일 한다. 

또한, 형 타입도 정적으로 선언 할 수 있는 기능도 제공한다.

이런 동적 기능들로 인해 반복문이 많이 사용되는 경우 파이썬에 비해 수 십에서 수백 배까지 수행 속도를 증가 시킬 수 있다.

따라서, 사이썬은 C언어로된 함수를 파이썬 문법에서 부를 수 있도록 적극 지원하는 양식이다. 











---------------------------------------------------------------------

helloword.pyx

setup.py

python setup.py build_ext --inplace
helloworld.so 또는 helloworld.pyd

shared object (공유) 파일 생성이 이루어진다.


----------------------------------------------------------------------
Cython을 활용하여 계산 속도를 높일 수 있다.

빨리 계산하기

기본 python 프로그램은 아래와 같다.

import time 
def count(limit):
    result = 0
    for a in range(1, limit + 1):
        for b in range(a + 1, limit + 1):
            for c in range(b + 1, limit + 1):
                if c * c > a * a + b * b:
                    break
 
                if c * c == (a * a + b * b):
                    result += 1
    return result
 
if __name__ == '__main__':
    start = time.time()
    result = count(1000)
    duration = time.time() - start
    print(result, duration)

----------------------------------------------------------------------

계산 속도 향상을 보려고 하는 핵심 함수를 아래의 이름으로 저장한다.
pythagorean_triples.pyx

import time
import pyximport; pyximport.install()
import pythagorean_triples
 
def main():
    start = time.time()
    result = pythagorean_triples.count(1000)
    duration = time.time() - start
    print(result, duration)
 
if __name__ == '__main__':
    main()


----------------------------------------------------------------------
setup.py 파일 작성

from distutils.core import setup
from Cython.Build import cythonize
 
setup(
    ext_modules = cythonize("pythagorean_triples.pyx")
)

$ python setup.py build_ext --inplace
Compiling pythagorean_triples.pyx because it changed.
[1/1] Cythonizing pythagorean_triples.pyx
running build_ext
building 'pythagorean_triples' extension
creating build
creating build/temp.macosx-10.7-x86_64-3.6
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code
-DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
-I/Users/gigi.sayfan/miniconda3/envs/py3/include
-arch x86_64 -I/Users/gigi.sayfan/miniconda3/envs/py3/include
-arch x86_64
-I/Users/gigi.sayfan/miniconda3/envs/py3/include/python3.6m
-c pythagorean_triples.c
-o build/temp.macosx-10.7-x86_64-3.6/pythagorean_triples.o
gcc -bundle -undefined dynamic_lookup
-L/Users/gigi.sayfan/miniconda3/envs/py3/lib
-L/Users/gigi.sayfan/miniconda3/envs/py3/lib
-arch x86_64
build/temp.macosx-10.7-x86_64-3.6/pythagorean_triples.o
-L/Users/gigi.sayfan/miniconda3/envs/py3/lib
-o pythagorean_triples.cpython-36m-darwin.so


import time
import pythagorean_triples
 
def main():
    start = time.time()
    result = pythagorean_triples.count(1000)
    duration = time.time() - start
    print(result, duration)
 
if __name__ == '__main__':
    main()



----------------------------------------------------------------------

#       pythagorean_triples.pyx
def count(limit):
    cdef int result = 0
    cdef int a = 0
    cdef int b = 0
    cdef int c = 0
 
    for a in range(1, limit + 1):
        for b in range(a + 1, limit + 1):
            for c in range(b + 1, limit + 1):
                if c * c > a * a + b * b:
                    break
 
                if c * c == (a * a + b * b):
                    result += 1
    return result
 
#        main.py
import time
import pyximport; pyximport.install()
import pythagorean_triples
 
def main():
    start = time.time()
    result = pythagorean_triples.count(1000)
    duration = time.time() - start
    print(result, duration)
 
if __name__ == '__main__':
    main()  
   
./pytha.py
(881, 10.488554000854492)
[ihlee@master chun20180524]$ ./pytha1.py
(881, 0.06052517890930176)
[ihlee@master chun20180524]$ ./pytha2.py
(881, 7.23646092414856)

실행 시간 측정 방법:
>>> import timeit
>>> timeit.timeit('count(1000)', setup='from pythagorean_triples import count', number=1)
0.05357028398429975
 
# Running 10 times
>>> timeit.timeit('count(1000)', setup='from pythagorean_triples import count', number=10)
0.5446877249924

------------------------------------------------------------------------------------   

파이썬에서 C 프로그램 부르기:

파이썬에서 Fortran 프로그램 부르기:

Pypy: 파이썬 코드를 수정하지 않고 실행속도 향상시키는 방법:
PyPy
------------------------------------------------------------------------------------  


------------------------------------------------------------------------------------  


핑백

덧글

  • Lim 2018/06/09 13:46 # 삭제 답글

    박사님, pypy도 한번 써보셔요 :) cython은 cython을 위한 코드를 따로 작성해야하는 것으로 알고 있는데, pypy는 기존의 python 코드를 그대로 사용할 수 있고, 속도도 Cython보다 빠른 것 같아요.
  • 바죠 2018/06/10 15:55 #

    중요한 정보 전달 감사드립니다.
    잘 지내시는지요?

  • Lim 2018/07/02 11:01 # 삭제 답글

    저는 잘 지내고 있습니다. 요즘 한창 manuscript작성 중이라 매일 figure만들고, 고치고, 글쓰고 하고 있어요 :)
    박사님도 잘 지내시죠?
  • 바죠 2018/07/02 12:52 # 답글

    저는 밤새 축구 보고 있습니다.
    좋은 논문 많이 발표하시길 바랍니다.

    덕분에 파이썬 강좌에서 pypy를 실습하는 시간을 가졌습니다.
    실습한 내용은 아래의 URL 참조:
    http://incredible.egloos.com/7414058

  • afwee 2020/07/10 18:17 # 삭제 답글

    기본 python 프로그램은 아래와 같다 바로 아래의 코드는 무슨 코드인가요?
    다른 python 함수나 pyx 를 호출하는 것 같지는 않은데 왜 적으신건가요?
  • 바죠 2020/07/11 10:17 #

    가장 먼저 파이썬 프로그램이 있다고 생각합니다. 그런데 계산 시간이 너무 오래 걸리는 경우입니다.
    계산 속도 향상을 기대합니다. 싸이썬으로 변환을 기대합니다.
댓글 입력 영역

최근 포토로그