使用rust-cpython从Rust并行运行Python代码

时间:2020-02-10 11:01:03

标签: python rust cpython

我正在尝试使用Rust加速数据管道。该管道包含一些我不想修改的Python代码,因此我试图使用rust-cpython和多个线程从Rust照原样运行它们。 但是,性能不是我期望的,实际上与在单个线程中按顺序运行python代码位相同。

在阅读文档时,我了解到在调用以下内容时,您实际上会获得一个指向只能创建一次的Python解释器的指针,即使您从多个线程分别运行它也是如此。

if (voterIC == "") {
  $("#messageEdit").html("<h4 style=\"color:red\">Please fill in NRIC!</h4>");
} else {
  obj = new Object();
  obj.NRIC = voterIC;
  obj.CreatedDate = firebase.database.ServerValue.TIMESTAMP;
}

如果是这种情况,则意味着Python GIL实际上也阻止了Rust中的所有并行执行。有办法解决这个问题吗?

这是我测试的代码:

    let gil = Python::acquire_gil();
    let py = gil.python();

1 个答案:

答案 0 :(得分:2)

Python的CPython实现不允许在多个线程中同时执行Python bytecode 。如您所知,全局解释器锁定(GIL)可以防止这种情况。

关于您的Python代码到底在做什么,我们没有任何信息,因此,我将提供一些一般性提示,以帮助您提高代码的性能。

  • 如果您的代码受I / O限制,例如从网络中读取数据,使用多个线程通常会获得不错的性能改进。阻塞的I / O调用将在阻塞之前释放GIL,以便其他线程可以在这段时间内执行。

  • 某些库,例如NumPy,在长时间运行的库调用期间内部释放了GIL,不需要访问Python数据结构。使用这些库,即使仅使用该库编写纯Python代码,也可以提高多线程,CPU绑定代码的性能。

  • 如果您的代码受CPU限制并且花费大量时间执行Python字节码,则通常可以使用multipe 进程而不是线程来实现并行执行。 Python标准库中的multiprocessing对此提供了帮助。

  • 如果您的代码受CPU限制,则将其大部分时间用于执行Python字节码 ,并且由于它访问共享数据,因此无法在并行进程中运行,因此您无法运行它在多个并行线程中– GIL防止了这种情况。但是,即使没有GIL,也不能不更改任何语言而仅并行运行顺序代码。由于您可以同时访问某些数据,因此需要添加锁定并可能进行算法更改以防止数据竞争。具体操作方法取决于您的用例。 (如果您没有具有并发数据访问权限,则应使用进程而不是线程–参见上文。)

除了并行性之外,使用Rust加速Python代码的一种好方法是配置您的Python代码,找到大部分时间都花在的热点,将这些位重写作为您从Python代码调用的Rust函数。如果这样做不能给您带来足够的提速,则可以结合这种方法与并行性–与大多数其他语言相比,在Rust中防止数据竞争通常更容易实现。

相关问题