파이썬은 멀티스레딩을 통해 동시에 여러 작업을 수행할 수 있는 강력한 언어입니다. 하지만, GIL(Global Interpreter Lock)이라는 개념 때문에 파이썬에서는 실제로 동시에 여러 CPU 코어를 활용하여 병렬 처리를 할 수 없습니다. 따라서, 파이썬에서의 멀티스레딩은 I/O 바운드 작업을 처리하거나 CPU 바운드 작업을 분할하여 병렬로 처리하는 등의 용도로 활용됩니다.
만약 C/C++로 작성된 라이브러리나 모듈을 파이썬에서 사용하고자 할 때, 파이썬 모듈을 작성하기 위해 PyO3라는 도구를 사용할 수 있습니다. PyO3는 파이썬의 C API를 편리하게 사용할 수 있도록 도와주는 도구이며, C/C++ 코드를 사용하는 고성능 파이썬 모듈을 작성할 수 있도록 지원합니다.
PyO3를 활용하여 작성한 파이썬 모듈에서 멀티스레딩을 지원하기 위해서는 threading
라이브러리를 사용할 수 있습니다. threading
라이브러리는 파이썬에서 멀티스레딩을 구현하는 데 사용되는 기본 라이브러리이며, 여러 개의 스레드를 생성하고 조작하는 기능을 제공합니다.
다음은 PyO3를 활용하여 작성된 파이썬 모듈에서 멀티스레딩을 구현하는 예시 코드입니다.
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
fn calculate_square(num: u32) -> u32 {
num * num
}
#[pyfunction]
fn calculate_squares(numbers: Vec<u32>) -> PyResult<Vec<u32>> {
let gil = Python::acquire_gil();
let py = gil.python();
let mut result = vec![];
py.allow_threads(|| {
let n = numbers.len();
let threads = 4; // Number of threads to use
let chunk_size = (n + threads - 1) / threads;
let chunks = numbers.chunks(chunk_size);
pyo3::ff::threading::Scope::new(py)
.launch(|scope| {
for chunk in chunks {
scope.spawn(move |_| {
let squares: Vec<u32> = chunk.iter()
.map(|&num| calculate_square(num))
.collect();
result.extend(squares);
});
}
})
.unwrap();
});
Ok(result)
}
#[pymodule]
fn my_module(py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(calculate_squares, m)?)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use pyo3::types::IntoPyDict;
use pyo3::types::PyList;
#[test]
fn test_calculate_squares() {
let gil = Python::acquire_gil();
let py = gil.python();
my_module(py, pyo3::types::PyModule::new(py, "my_module").unwrap()).unwrap();
let locals = [("my_module", py.import("my_module")?)].into_py_dict(py);
let input_data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let expected_output = vec![1, 4, 9, 16, 25, 36, 49, 64, 81, 100];
let result = py
.eval("my_module.calculate_squares([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])", Some(locals), None)
.unwrap();
let result_vec: Vec<u32> = result.extract().unwrap();
assert_eq!(result_vec, expected_output);
}
}
위의 예시 코드에서는 calculate_squares
라는 함수가 있는 파이썬 모듈을 작성하고 있습니다. 이 함수는 numbers
라는 입력 리스트를 받아 각 요소의 제곱을 계산하여 결과 리스트를 반환합니다. 이 때, threading
라이브러리를 사용하여 멀티스레딩을 구현하고 있습니다. 입력 리스트를 여러 개의 청크로 나누고, 각 청크를 병렬로 처리하여 결과를 합치는 방식으로 동작합니다.
모듈 작성이 완료되면, Rust 코드를 빌드하여 파이썬 모듈을 생성할 수 있습니다. 이후, 파이썬에서 해당 모듈을 가져와 멀티스레딩을 활용할 수 있습니다.
이와 같이 PyO3를 활용하여 파이썬 모듈을 작성하고 멀티스레딩을 지원하는 방법을 알아보았습니다. 파이썬의 멀티스레딩 기능을 활용하면 병렬 처리가 필요한 작업을 효율적으로 처리할 수 있습니다.
더 자세한 내용을 알고 싶다면 PyO3 공식 문서를 참고해주세요. #파이썬 #멀티스레딩