Python

Cython 시작하기 (튜토리얼)

Cython

https://cython.org/

What is Cython?

Cython은 C라이크한 정적 타이핑을 지원하고, C로 구현된 함수들을 바로 호출할 수 있게 해준다. OpenMP 를 지원하기 때문에 주로 계산 코드를 더 빠르게 변경하기 위해 사용되기도 한다. (이때 스레드는 파이썬 코드가 아니라 C코드 레벨에서 동작한다.)

Cython을 사용하는 라이브러리로는 scipy, scikit-learn, lxml, zmq등이 있다.

How to use?

컴파일된 확장 모듈을 작성하는 괒엉에는 세 가지 파일이 관여한다.

setup.py 스크립트에서 Cython을 사용해 .pyx 파일을 컴파일한다. 유닉스류 시스템에서는 .so 파일이 만들어지며 윈도우에서는 DLL과 비슷한 파이썬 라이브러리인 .pyd파일로 만들어진다.

Hello World

Cython의 구조

스크립트 작성

hello.pyx

from libc.math cimport pow

cdef double square_and_add(double x):
    return pow(x, 2.0) + x

cpdef print_result(double x):
    print("({} ^ 2) + {} = {}".format(x, x, square_and_add(x)))
    

setup.py

from distutils.core import Extension, setup
from Cython.Build import cythonize

ext = Extension(name="hello", sources=["hello.pyx"])
setup(ext_modules=cythonize(ext))

test.py

import hello

# Test!
hello.print_result(23.0)

컴파일

  1. Cython 파일을 컴파일합니다.
  python3 setup.py build_ext --inplace
  1. 임포트하여 실행합니다.

    python3 test.py
    

Fibonacci (def vs cdef vs cpdef)

pyfibonacci.py

def fib(n):
    if n < 2:
        return n
    return fib(n-2) + fib(n-1)
    

cyfibonacci.pyx

def fib(n):
    if n < 2:
        return n
    return fib(n-2) + fib(n-1)

def fib_int(int n):
    if n < 2:
        return n
    return fib(n-2) + fib(n-1)

def fib_cdef(int n):
    return fib_in_c(n)

cdef int fib_in_c(int n):
    if n < 2:
        return n
    return fib_in_c(n-2) + fib_in_c(n-1)

cpdef fib_cpdef(int n):
    if n < 2:
        return n
    return fib_cpdef(n-2) + fib_cpdef(n-1)
    

성능 비교

$ python3 comparison.py
<function fib at 0x10e0888c8> 0.3334619998931885
<built-in function fib> 0.0830848217010498
<built-in function fib_int> 0.08296680450439453
<built-in function fib_cdef> 0.004754066467285156
<built-in function fib_cpdef> 0.02499103546142578
function time(ms) ratio
pyfibonacci.fib(30) 0.3334 70.93
cyfibonacci.fib(30) 0.0830 17.65
cyfibonacci.fib_int(30) 0.0829 17.63
cyfibonacci.fib_cdef(30) 0.0047 1.00
cyfibonacci.fib_cpdef(30) 0.0249 5.29

코드 블록 분석을 위한 Cython 애너테이션

$ cython -a cyfibonacci.pyx

위의 명령을 실행하면 cyfibonacci.html 파일이 생성된다. 그 파일을 브라우저로 확인해보면 아래와 같다.

screenshot_cythonfn

코드의 각 줄을 누르면 생성된 C코드를 확인할 수 있다. 짙은 노란색은 파이썬 가상머신에서 더 많이 실행됐다는 것을 나타낸다. 옅은 노란색일 수록 파이썬이 아닌 C코드가 더 많음을 나타낸다. 노란색 코드를 가능한 줄여서 옅은 색이 더 많아지도록 하는 것이 목표가 된다. 반복문 안에서의 노란색 줄을 해결하는 것이 의미가 훨씬 크다.

Attach numpy

참고할만한 자료

import numpy as np
cimport numpy as np


def do_stuff():
    print("Hello World!")
    cdef int n
    n = 2
    r = np.random.randint(1,5)
    print("A random number: "+str(r))
    print("A random number multiplied by 2 (made by cdef):"+str(r*n))
    input("Press Enter to continue.")