Skip to content

Cython

사이썬(Cython)은 CPython 확장 모듈을 손쉽게 생성하도록 고안된 컴파일 언어이다. 파이썬 문법을 기반으로 C/C++ 루틴을 호출을 위한 외부 함수 인터페이스와 실행 속도 향상을 위한 정적 형 지정 등이 추가된 형태를 하고 있다. 이러한 특징은 파이썬의 빠른 생산성을 유지하면서도 외부 C 라이브러리와 간결하게 연동하거나 실행 속도 향상 할 수 있도록 해준다.

Categories

  • Recc:cython

Simple Example

우선 helloworld.pyx파일로 아래와 같이 저장한다.

print "Hello World"

setup.py파일을 만들고 아래와 같이 컴파일할 파일명을 입력한다.

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

아래와 같이 실행하면 동적 라이브러리가 만들어 진다.

$ python setup.py build_ext --inplace

실제 사용은 일반 Python과 같이 적용하면 된다.

import helloworld

More simple

아래와 같이 입력하면 *.c파일이 생성된다. 이 파일을 gcc등으로 컴파일 하면 된다.

$ cython helloworld.pyx

Flags

--embed
단일파일로 임베드한다? - 좀더 확인.

Source Files and Compilation

C-Flags

Packaging

setup.py설정tox, devpi 등에서 일반적으로 배포시 사용하는 명령은 sdist 이다.

Single file compile

WARNING

ChatGPT 답변 결과임. 확인 필요

extensions = [
    Extension(
        name="your_module",  # 모듈 이름
        sources=["module1.pyx", "module2.pyx", "module3.py"],  # 파일들
        extra_compile_args=["-O3"],  # 컴파일러 최적화 플래그
        extra_link_args=[]  # 추가적인 링킹 플래그
    )
]

setup(
    ext_modules=cythonize(extensions)
)

Pure Python Benchmark

다음 test.py 코드를 Cython 버전과, Python 버전으로 돌렸을 때 성능차이를 확인했다.

import math

def test(a):
    mean = sum(a) / len(a)
    return math.sqrt((sum(((x - mean)**2 for x in a)) / len(a)))

Cython 모듈을 만들기 위한 setup.py 파일:

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("test.py")
)

컴파일은 다음과 같이 실행.

python setup.py build_ext --inplace

테스트 코드는 다음과 같다:

import datetime
import sys

from test import test as test1  # Cython method.
from test2 import test as test2  # Python method.


if __name__ == "__main__":
    a = [i for i in range(100000000)]

    now = datetime.datetime.now()
    k = test1(a)
    print("cython:", datetime.datetime.now() - now)

    now = datetime.datetime.now()
    k = test2(a)
    print("python:", datetime.datetime.now() - now)

    exit(0)

성능 차이는 다음과 같다:

cython: 0:00:25.082879
python: 0:00:30.424469

1억번 루프를 돌렸을 경우 5초 차이로 Cython 승!

Troubleshooting

FutureWarning language_level not set

language_level을 설정한다. *.pyx 파일 첫 줄에 다음 주석을 추가하면 된다.

# cython: language_level=3

Customize location of .so file generated by Cython

setup.py를 다음과 같이 적용한다.

from setuptools import setup, find_packages, Extension
from Cython.Distutils import build_ext

ext_modules=[
    Extension("package.wrapper.wrap",    # location of the resulting .so
             ["package/wrapper/wrap.pyx"],) ]


setup(name='package',
      packages=find_packages(),
      cmdclass = {'build_ext': build_ext},
      ext_modules = ext_modules,
     )

그리고 다음과 같이 컴파일한다.

python setup.py build_ext --inplace

cython 파일을 setup.py 에 위치시키는 방법

Resolved through corrected MANIFEST.in:

global-include *.txt *.rst *.pyx *.pxd *.c *.h

setup.py:

setup(
    include_package_data=True,
    package_data={'': ['data/*', '*.pyx', '*.pxd', '*.c', '*.h']},
)

MANIFEST.in and setup.py must both cover all file patterns to support bdist and sdist.

error: each element of 'ext_modules' option must be an Extension instance or 2-tuple

error: each element of 'ext_modules' option must be an Extension instance or 2-tuple

Cython 패키지를 포함시킬 때 setuptools보다 먼저 추가되면 안된다:

# from Cython.Build import cythonize  # BED CODE !!!!
from setuptools import find_packages, setup
from setuptools.command.build_py import build_py

from Cython.Build import cythonize  # Correct CODE !!!!

See also

Favorite site

Basic