我正在使用并行处理来生成使用复数的函数图。我的脚本允许您使用标准 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)
即可解决此问题,这意味着脚本仍然有效。
我对并行处理还很陌生,因此我对任何人都可以提供的有关阻止并行处理工作所缺少的内容的更多信息非常感兴趣。
关于Python - 从 mpl_connect 处理程序调用时 ProcessPoolExecutor 挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60427864/