我正在尝试使用 Rust 加速数据管道。该管道包含一些我不想修改的 Python 代码,因此我尝试使用 Rust 按原样运行它们rust-cpython https://docs.rs/cpython/0.4.1/cpython/和多线程。
然而,性能并没有达到我的预期,它实际上与在单个线程中顺序运行 python 代码位相同。
阅读文档后,我了解到,在调用以下内容时,您实际上会获得一个指向单个 Python 解释器的指针,该解释器只能创建一次,即使您分别从多个线程运行它也是如此。
let gil = Python::acquire_gil();
let py = gil.python();
如果是这种情况,则意味着 Python GIL 实际上也阻止了 Rust 中的所有并行执行。有办法解决这个问题吗?
这是我的测试代码:
use cpython::Python;
use std::thread;
use std::sync::mpsc;
use std::time::Instant;
#[test]
fn python_test_parallel() {
let start = Instant::now();
let (tx_output, rx_output) = mpsc::channel();
let tx_output_1 = mpsc::Sender::clone(&tx_output);
thread::spawn(move || {
let gil = Python::acquire_gil();
let py = gil.python();
let start_thread = Instant::now();
py.run("j=0\nfor i in range(10000000): j=j+i;", None, None).unwrap();
println!("{:27} : {:6.1} ms", "Run time thread 1, parallel", (Instant::now() - start_thread).as_secs_f64() * 1000f64);
tx_output_1.send(()).unwrap();
});
let tx_output_2 = mpsc::Sender::clone(&tx_output);
thread::spawn(move || {
let gil = Python::acquire_gil();
let py = gil.python();
let start_thread = Instant::now();
py.run("j=0\nfor i in range(10000000): j=j+i;", None, None).unwrap();
println!("{:27} : {:6.1} ms", "Run time thread 2, parallel", (Instant::now() - start_thread).as_secs_f64() * 1000f64);
tx_output_2.send(()).unwrap();
});
// Receivers to ensure all threads run
let _output_1 = rx_output.recv().unwrap();
let _output_2 = rx_output.recv().unwrap();
println!("{:37} : {:6.1} ms", "Total time, parallel", (Instant::now() - start).as_secs_f64() * 1000f64);
}