繁体   English   中英

Python - 从 mpl_connect 处理程序调用时 ProcessPoolExecutor 挂起

[英]Python - ProcessPoolExecutor hangs when called from a mpl_connect handler

我正在使用并行处理来生成使用复数的函数图。 我的脚本允许您使用标准 matplotlib 控件放大绘图区域,然后在新限制内重新生成绘图以提高分辨率。

这是我第一次涉足并行处理,据我所知,我需要以if __name__ == __main__:以允许正确导入模块。 运行我的脚本时,第一个图已成功生成并按预期显示。 但是,当从我的事件处理程序再次调用绘图函数时,它会无限期地挂起。 我认为挂起是由与if __name__ == __main__:类似的问题引起的,因为并行进程是从脚本主体外部产生的,但我还没有想出比这更进一步的东西。

import numpy as np
import matplotlib.pyplot as plt
from concurrent.futures import ProcessPoolExecutor
import multiprocessing

res = [1000, 1000]
base_factor = 2.
cpuNum = multiprocessing.cpu_count()

def brot(c, depth=200):
    z = complex(0)

    for i in range(depth):
        z = pow(z, 2) + c

        if abs(z) > 2:
            return i

    return -1

def brot_gen(span):
    re_span = span[0]
    im_span = span[1]

    mset = np.zeros([len(im_span), len(re_span)])

    for re in range(len(re_span)):
        for im in range(len(im_span)):
            mset[im][re] = brot(complex(re_span[re], im_span[im]))

    return mset

def brot_gen_parallel(re_lim, im_lim):
    re_span = np.linspace(re_lim[0], re_lim[1], res[0])
    im_span = np.linspace(im_lim[0], im_lim[1], res[1])

    split_re_span = np.array_split(re_span, cpuNum)

    packages = [(sec, im_span) for sec in split_re_span]
    print("Generating set between", re_lim, "and", im_lim, "...")

    with ProcessPoolExecutor(max_workers = cpuNum) as executor:
            result = executor.map(brot_gen, packages)

    mset = np.concatenate(list(result), axis=1)
    print("Set generated")

    return mset

def handler(ax):
    def action(event):
        if event.button == 2:
            cur_re_lim = ax.get_xlim()
            cur_im_lim = ax.get_ylim()

            mset = brot_gen_parallel(cur_re_lim, cur_im_lim)

            ax.cla()
            ax.imshow(mset, extent=[cur_re_lim[0], cur_re_lim[1], cur_im_lim[0], cur_im_lim[1]], origin="lower", vmin=0, vmax=200, interpolation="bilinear")

            plt.draw()

    fig = ax.get_figure()
    fig.canvas.mpl_connect('button_release_event', action)

    return action

if __name__ == "__main__":
    re_lim = np.array([-2.5, 2.5])
    im_lim = res[1]/res[0] * re_lim

    mset = brot_gen_parallel(re_lim, im_lim)

    plt.imshow(mset, extent=[re_lim[0], re_lim[1], im_lim[0], im_lim[1]], origin="lower", vmin=0, vmax=200, interpolation="bilinear")

    ax = plt.gca()

    f = handler(ax)

    plt.show()

编辑:我想知道代码中是否存在导致异常的错误,但这可能无法成功传递回控制台,但是我通过运行相同的任务而不将其拆分为并行任务进行了测试,并且它成功完成。

我已经找到了我自己问题的答案。 答案在于我使用的 IDE。 根据我的经验,在大多数 IDE 中plt.show()默认情况下会阻止执行,但是在 Spyder 中,默认值似乎相当于plt.show(block=False) ,这意味着脚本已完成,因此成功启动所需的任何内容并行进程不再可用,导致挂起。 这可以通过简单地将语句更改为plt.show(block=True) ,这意味着脚本仍然有效。

我对并行处理还是很陌生,所以我对任何人都可以提供的关于阻止并行处理工作所缺乏的信息非常感兴趣。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM