-
Rust: PyO3 파이썬 모듈 Rust 언어로 만들기컴퓨터/Rust 2021. 4. 24. 19:52728x90반응형
Rust
1. 소개
CPython API를 통해 Python 모듈을 빠르게 만드는 방법과 같이 Rust로 만들 수 있다.
Rust로 만들 경우 몇 % 의 성능 향상이 있을진 모른다. gil 사용 안 한 parallelism 성능은 다음과 같이 나와있다.
(단순 단어 세는 프로그램, rust로 만들어 쓸 경우가 훨씬 빠르다.)
-------------------------------------------------------------------------------------------------- benchmark: 4 tests ------------------------------------------------------------------------------------------------- Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- test_word_count_rust_parallel 1.7315 (1.0) 4.6495 (1.0) 1.9972 (1.0) 0.4299 (1.0) 1.8142 (1.0) 0.2049 (1.0) 40;46 500.6943 (1.0) 375 1 test_word_count_rust_sequential 7.3348 (4.24) 10.3556 (2.23) 8.0035 (4.01) 0.7785 (1.81) 7.5597 (4.17) 0.8641 (4.22) 26;5 124.9457 (0.25) 121 1 test_word_count_rust_sequential_twice_with_threads 7.9839 (4.61) 10.3065 (2.22) 8.4511 (4.23) 0.4709 (1.10) 8.2457 (4.55) 0.3927 (1.92) 17;17 118.3274 (0.24) 114 1 test_word_count_python_sequential 27.3985 (15.82) 45.4527 (9.78) 28.9604 (14.50) 4.1449 (9.64) 27.5781 (15.20) 0.4638 (2.26) 3;5 34.5299 (0.07) 35 1 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2. 예제
setup.py
setuptools_rust를 따로 설치해야 함
pip install setuptools setuptools_rust python setup.py install
from setuptools import setup from setuptools_rust import Binding, RustExtension def call_setup(): setup( name="module_name", version="0.0.1", description="PyPI 설명", # long_description=open("README.rst", encoding="utf-8").read(), # long_description_content_type="text/x-rst", keywords="rust", author="Seok Won", author_email="@kakao.com", maintainer="", maintainer_email="@kakao.com", python_requires=">=3.5", license="MIT", rust_extensions=[RustExtension("module_name", binding=Binding.PyO3)], classifiers=[ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Rust", ], zip_safe=False, ) if __name__ == "__main__": call_setup()
lib.rs
pymethod, pyclass 등의 attributes를 사용해서 pymodule에 알려주어야 함
cargo run이 아닌, python setup.py install을 할 때 알아서 빌드하고 설치된다.
extern crate pyo3; use pyo3::prelude::*; use pyo3::types::PyList; use pyo3::PyObjectProtocol; #[pyclass(subclass)] pub struct Human { #[pyo3(get)] name: String, #[pyo3(get)] age: u8, #[pyo3(get)] salary: u32, } #[pymethods] impl Human { #[new] fn new(name: String, age: u8, salary: u32) -> Self { Human { name, age, salary } } fn promote(&mut self, salary: u32) { self.salary = salary; } fn string(&self) -> PyResult<String> { let str = format!("I am {}!", self.name).to_string(); Ok(str) } } #[pyproto] impl PyObjectProtocol for Human { fn __str__(&self) -> PyResult<&'static str> { Ok(format!("Human: name({})", self.name)) } fn __repr__<'a>(&'a self) -> PyResult
{ Ok(format!("Human name: {}", self.name)) } } #[pyfunction] fn bubble(_py: Python, array: &PyList) -> PyResult<()> { let mut count = 0; let mut is_sorted = false; let n = array.len() - 1; while !is_sorted { is_sorted = true; for i in 0..(n - count) as isize { let first = array.get_item(i); let second = array.get_item(i + 1); match first.compare(second).unwrap() { Ordering::Greater => { array.set_item(i, second)?; array.set_item(i + 1, first)?; is_sorted = false; } _ => {} } } count += 1; } Ok(()) } #[pymodule] fn rust_sort(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::<Human>()?; m.add_function(wrap_pyfunction!(bubble, m)?)?; Ok(()) } test.py
rust_sort로 만들고 위의 bubble 함수와 Human 클래스를 import 했다.
from rust_sort import bubble, Human def bubble_test(): a = [5, -2, 3, 0, 11] bubble(a) print(a) # [-2, 0, 3, 5, 11] def class_test(): print() human = Human("A1", 37, 1200) print(human.salary) # 1200 human.promote(1500) print(human.salary) # 1500 print(human.string()) # I am A1! if __name__ == "__main__": bubble_test() class_test()
참고
공식 문서: pyo3.rs/
PyO3 Github (여러 가지 example을 볼 수 있음): github.com/PyO3/pyo3
위 소스 Github 링크: github.com/Alfex4936/Rust-PyO3-Example
728x90'컴퓨터 > Rust' 카테고리의 다른 글
Rust 문법: dyn, trait, polymorphism (0) 2021.05.02 Rust 문법: Ownership (소유권) (0) 2021.04.24 RustPython: Rust로 작성된 파이썬 인터프리터 (0) 2021.02.07