Как применить многопроцессорный модуль на моем PyQt-GUI - PullRequest
0 голосов
/ 03 октября 2019

Я знаю, что это старый вопрос, и уже нашел ответы на другие вопросы, подобные этой теме здесь . Тем не менее, у меня есть некоторые проблемы с применением его в моем случае.

У меня сейчас есть следующие вещи: у меня есть класс MainWindow, где я могу вводить некоторые данные. Затем у меня есть класс Worker, который является объектом PySide2.QtCore.QThread. В этот класс я передаю некоторые входные данные из MainWindow. Внутри этого класса Worker у меня есть метод, который устанавливает некоторые ODE, которые в другом методе класса Worker решаются с помощью scipy.integrate.solve_ivp. Когда интеграция завершена, я посылаю результаты через сигнал обратно в MainWindow. Таким образом, код выглядит примерно так:

import PySide2
from scipy.integrate import solve_ivp

class Worker(QtCore.QThread):

    def __init__(self,*args,**kwargs):
        super(Worker,self).__init__()
        "Here I collect input parameters"

    def run(self):
        "Here I call solve_ivp for the integration and send a signal with the 
        solution when it is done"

    def ode_fun(self,t,c):
        "Function where the ode equations are set up"


class Ui_MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        "set up the GUI"
        self.btnStartSimulation.clicked.connect(self.start_simulation) #button to start the integration

    def start_simulation(self):
        self.watchthread(Worker)
        self.thread.start()

    def watchthread(self,worker):
        self.thread = worker("input values")
        "connect to signals from the thread"

Теперь я понимаю, что с помощью многопроцессорного модуля я смогу запустить поток с интеграцией на другое ядро ​​процессора, чтобы сделать его быстрее и сделать графический интерфейс меньше. лаг. Однако по ссылке выше я не уверен, как мне применить этот модуль или даже как реструктурировать мой код. Должен ли я поместить код, который у меня сейчас есть в моем классе Worker, в другой класс, или я каким-то образом могу применить многопроцессорный модуль в моем существующем потоке? Любая помощь очень ценится!

Редактировать: Новый код выглядит следующим образом:

class Worker(QtCore.QThread):

    def __init__(self,*args,**kwargs):
        super(Worker,self).__init__()
        self.operation_parameters = args[0]
        self.growth_parameters = args[1]
        self.osmolality_parameters = args[2]
        self.controller_parameters = args[3]
        self.c_zero = args[4]

    def run(self):
        data = multiprocessing.Queue()
        input_dict = {"function": self.ode_fun_vrabel_rushton_scaba_cont_co2_oxygen_biomass_metabol,
                      "time": [0, self.t_final],
                      "initial values": self.c_zero}
        data.put(input_dict)
        self.ode_process = multiprocessing.Process(target=self.multi_process_function, args=(data,))
        self.ode_process.start()

        self.solution = data.get()

    def multi_process_function(self,data):
        self.message_signal = True
        input_dict = data.get()
        solution = solve_ivp(input_dict["function"], input_dict["time"],
                      input_dict["initial values"], method="BDF")
        data.put(solution)

    def ode_fun(self,t,c):
        "Function where the ode equations are set up"
        (...) = self.operation_parameters
        (...) = self.growth_parameters
        (...) = self.osmolality_parameters
        (...) = self.controller_parameters

Это нормально, если я получаю доступ к параметрам в функции ode_fun через self. "Имя_параметра"? Или я также должен передать их с параметром данных? С текущим кодом я получаю следующую ошибку: TypeError: не могу выбрать рабочие объекты

1 Ответ

0 голосов
/ 04 октября 2019

Вы можете назвать это у своего работника следующим образом:

import PySide2
from scipy.integrate import solve_ivp
import multiprocessing

class Worker(QtCore.QThread):

    def __init__(self,*args,**kwargs):
        super(Worker, self).__init__()
        self.ode_process = None

        "Here I collect input parameters"

    def run(self):
        "Here I call solve_ivp for the integration and send a signal with the solution when it is done"
        data = multiprocessing.Queue()
        data.put("all objects needed in the process, i would suggest a single dict from which you extract all data")
        self.ode_process = multiprocessing.Process(target="your heavy duty function", args=(data,))
        self.ode_process.start()  # this is non blocking

        # if you want it to block:
        self.ode_process.join()
        # make sure you remove all input data from the queue and fill it with the result, then to get it back:
        results = data.get()

        print(results)  # or do with it what you want to do...

    def ode_fun(self, t, c):
        "Function where the ode equations are set up"


class Ui_MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        "set up the GUI"
        self.btnStartSimulation.clicked.connect(self.start_simulation) #button to start the integration

    def start_simulation(self):
        self.watchthread(Worker)
        self.thread.start()

    def watchthread(self,worker):
        self.thread = worker("input values")
        "connect to signals from the thread"

Также имейте в виду, что теперь вы будете перезаписывать запущенный процесс при каждом нажатии для запуска симуляции. Вы можете использовать какой-то замок для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...