当顺序调用之后进行多处理调用时,Python 程序会冻结

问题描述 投票:0回答:1

我在使用

pyvips
库处理图像的 Python 程序中遇到了一个奇怪的问题。这是我的问题的简化版本。

我尝试多次创建一个 numpy 数组(在我的简单示例中来自零)(在示例中为 2 次)。

当我按顺序执行时,一切都很好。当我使用

multiprocessing
模块时,它也能正常工作。但在我的测试过程中,我注意到当我依次快速执行这两个运行时,程序会冻结。因此就有了下面的程序。当我运行它时,它在多处理部分的第一个“步骤 3”之前冻结。

我认为它与垃圾收集机制有关,但我在这里迷失了。

我正在使用 python 3.11.3 和 pyvips 2.2.2(带有 vips-8.15.1)。我在 Linux 机器(基于 Ubuntu 22.04 的发行版)上使用 Spyder 及其 IPython 控制台。

import multiprocessing
import numpy as np
import pyvips

def myfunction(useless):
    print("step 1")
    image = pyvips.Image.new_from_array(np.zeros((8, 8, 3)), interpretation="rgb")
    print("step 2")
    res = np.asarray(image)
    print("step 3")
    return res

def main(nbpool):
    srcrange = range(2)
    if nbpool == 0:
        res = list()
        for srcid in srcrange:
            res.append(myfunction(srcid))
        return res
    else:
        pool = multiprocessing.Pool(nbpool)
        return pool.map(myfunction, srcrange)

if __name__ == "__main__":
    res1 = main(0)
    print("Now with multiprocessing")
    res2 = main(1)
python multiprocessing vips
1个回答
0
投票

您遇到的问题可能是由于多处理模块无法与 IPython 或 Jupyter 笔记本兼容。这是因为这些环境不是分叉安全的,并且多处理依赖于安全分叉 Python 解释器的能力。

潜在解决此问题的一种方法是在脚本开头使用 multiprocessing.set_start_method('spawn') 。这将使多处理模块为每个子进程创建一个新的 Python 解释器,这可以避免在非分叉安全的环境中分叉的问题。

以下是修改脚本的方法:

import multiprocessing
import numpy as np
import pyvips

# Set the start method for multiprocessing
multiprocessing.set_start_method('spawn')

def myfunction(useless):
    print("step 1")
    image = pyvips.Image.new_from_array(np.zeros((8, 8, 3)), interpretation="rgb")
    print("step 2")
    res = np.asarray(image)
    print("step 3")
    return res

def main(nbpool):
    srcrange = range(2)
    if nbpool == 0:
        res = list()
        for srcid in srcrange:
            res.append(myfunction(srcid))
        return res
    else:
        pool = multiprocessing.Pool(nbpool)
        return pool.map(myfunction, srcrange)

if __name__ == "__main__":
    res1 = main(0)
    print("Now with multiprocessing")
    res2 = main(1)

请注意,使用“spawn”启动方法可能会导致程序运行速度变慢,因为必须为每个子进程创建一个新的Python解释器。但是,它可以帮助避免在 IPython 或 Jupyter 笔记本等环境中分叉的问题。

© www.soinside.com 2019 - 2024. All rights reserved.