Я использую параллельную обработку для генерации графика функций с использованием комплексных чисел. Мой сценарий позволяет вам увеличивать область графика, используя стандартные элементы управления 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()
РЕДАКТИРОВАТЬ: я задавался вопросом, была ли ошибка в коде, вызывающая исключение, но что это не может быть успешно передано обратно на консоль, однако я протестировал это, выполнив ту же задачу, не разбивая ее на параллельные задачи, и она успешно выполнена.