跳转到主要内容

concurrent.futures.ProcessPoolExecutor的健壮实现

项目描述

Loky logo

可重用进程池执行器

Build Status Documentation Status codecov DOI

目标

本项目的目的是提供一个健壮、跨平台和跨版本的concurrent.futures.ProcessPoolExecutor类的实现。它特别具有以下特性

  • 一致且健壮的spawn行为:在POSIX系统上,所有进程都是通过fork + exec启动的。这确保了与第三方库更安全的交互。相比之下,multiprocessing.Pool默认使用不带exec的fork,导致第三方运行时崩溃(例如OpenMP、macOS Accelerate...)。

  • 可重用执行器:避免每次都重新启动完整执行器的策略。单例执行器实例可以在连续调用中重复使用(如果需要,可以动态调整大小),以限制启动和关闭开销。工作进程可以在配置的空闲超时后自动关闭,以释放系统资源。

  • 透明云pickle集成:并行调用交互式定义的函数和lambda表达式。还可以注册自定义序列化实现来处理进程间通信。

  • 脚本中不需要if __name__ == "__main__"::由于使用cloudpickle调用定义在__main__模块中的函数,因此在Windows下不需要保护调用并行函数的代码。

  • 无死锁实现:在标准的multiprocessingconcurrent.futures模块中,一个主要关注点是Pool/Executor处理工作进程崩溃的能力。这个库旨在解决可能的死锁问题,并返回有意义的错误。请注意,Python 3.7+附带的对concurrent.futures.ProcessPoolExecutor的实现与lokypool一样健壮,但lokypool也适用于旧版本的Python。

安装

推荐使用pip安装loky

pip install loky

loky也可以使用以下方式从源代码安装:

git clone https://github.com/joblib/loky
cd loky
python setup.py install

请注意,loky有一个可选的依赖项psutil,它允许早期检测内存泄漏。

用法

loky的基本用法依赖于get_reusable_executor,它内部管理一个自定义的ProcessPoolExecutor对象,该对象根据上下文重复使用或重新启动。

import os
from time import sleep
from loky import get_reusable_executor


def say_hello(k):
    pid = os.getpid()
    print(f"Hello from {pid} with arg {k}")
    sleep(.01)
    return pid


# Create an executor with 4 worker processes, that will
# automatically shutdown after idling for 2s
executor = get_reusable_executor(max_workers=4, timeout=2)

res = executor.submit(say_hello, 1)
print("Got results:", res.result())

results = executor.map(say_hello, range(50))
n_workers = len(set(results))
print("Number of used processes:", n_workers)
assert n_workers == 4

有关更高级的用法,请参阅我们的文档

贡献工作流程

要为loky做出贡献,首先在github上创建一个账户。完成此操作后,将lokypool存储库分叉以获得自己的存储库,然后在您希望工作的计算机上使用'git clone'克隆它。在您的克隆副本中做出更改,将它们推送到您的github账户,在多台计算机上进行测试,当您对它们满意时,向主存储库发送pull请求。

运行测试套件

要运行测试套件,您需要pytest(版本>= 3)和psutil模块。从项目的根目录运行测试套件:

    pip install -e .
    pytest .

为什么项目命名为loky

在开发loky时,我们在尝试调试使用multiprocessing.Poolconcurrent.futures.ProcessPoolExecutor时遇到了一些调试死锁的糟糕经历,特别是在项目初期调用带有不可序列化参数或返回值的函数时。当我们需要选择一个名称时,我们已经处理了这么多死锁,我们想要一些可以驱散它们的呼唤!因此,loky:神、锁和y的组合,使其有点酷和亲切:(而且也不太可能在谷歌搜索结果中产生名称冲突 ^^)。

为避免在concurrent.futures中的死锁而做出的修复也作为Python 3.7+的上游贡献,这是一种不太神秘的驱散死锁的方式 :D

致谢

这项工作得到数据科学中心的支持,该中心由IDEX Paris-Saclay资助,ANR-11-IDEX-0003-02

项目详细信息


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

loky-3.4.1.tar.gz (100.1 kB 查看哈希值)

上传时间 源代码

构建分发

loky-3.4.1-py3-none-any.whl (54.6 kB 查看哈希值)

上传时间 Python 3

由以下支持