【问题标题】:Update progressbar inside multiprocessor functions (Ray) simultaneously同时更新多处理器功能(Ray)内的进度条
【发布时间】:2022-06-24 04:13:16
【问题描述】:

我正在编写一个使用 ray 包进行多处理编程的程序。在程序中,有一个函数会同时被调用 5 次。在执行期间,我想使用 PyQT5 QprogressBar 显示一个进度条来指示完成了多少工作。我的想法是让函数的每次执行都将进度条更新 20%。所以我写了如下代码:

 running_tasks = [myFunction.remote(x,y,z,self.progressBar,QApplication) for x in myList]
 Results = list(ray.get(running_tasks))

在 myFunction 中,有一行更新发送的进度条,如下所示:

QApplication.processEvents()
progressBar.setValue(progressBar.Value()+20)

但是,当我运行代码时,出现以下错误:

TypeError:无法序列化参数 <PyQt5.QtWidgets.QProgressBar object at 0x000001B787A36B80> 用于任务 或演员 myFile.myFunction。查看 https://docs.ray.io/en/master/serialization.html#troubleshooting 为 更多信息。

我通过互联网搜索(URL返回404),我知道这个错误是因为ray中的多处理在处理器之间没有共享内存,并且发送一个类属性(如self.prgressBar)将导致每个处理器拥有它自己的副本,它将仅在本地对其进行修改。我也尝试使用 multiprocessing 包而不是 ray 但它会引发酸洗错误,我认为这是由于相同的原因。那么,谁能确认我是对的吗?或提供有关错误的进一步解释? 另外,如果多处理在处理器之间没有共享内存,我怎样才能达到我对多处理的要求(即同时更新相同的进度条)?

    标签: python parallel-processing pyqt5 multiprocessing ray


    【解决方案1】:

    我对 ray 不熟悉,但是您可以在多处理库中使用 multiprocessing.Queue() 来执行此操作。

    Queue 就像它的名字一样,是一个队列,您可以在其中放置数据以供其他多进程读取。就我而言,我通常在队列中放置一个带有命令(键)的字典以及如何处理该命令(值)。

    在一个多进程中,您将执行 Queue.put(),而在另一个多进程中,您可以执行 Queue.get()。如果你想通过一个方向。在下面的示例中,我模拟了您可能想要做的事情。

    我通常使用 QTimer 检查队列中是否有任何数据,但您也可以随时通过调用方法来检查。

    from multiprocessing import Process, Queue
    myQueue = Queue()
    
    class FirstProcess():
        ...
    
        def update_progress_percentage(self, percentage):
            self.progresss_percentage = percentage
    
        def send_data_to_other_process(self):
            myQueue.put({"UpdateProgress":self.progresss_percentage})
    
    class SecondProcess():
        ...
        
        def get_data_from_other_process(self):
            while not myQueue.empty():
                queue_dict = myQueue.get()
                for key in queue_dict :
                    if key == "UpdateProgress":
                        percentage = queue_dict["UpdateProgress"]
                        progressBar.setValue(percentage)
    

    【讨论】:

    • 您看到的酸洗错误是因为您试图通过队列传递 PyQt5 对象。酸洗是指您基本上保存整个类的状态并且 PyQt5 对象不能很好地酸洗。不过,您可以通过此队列传递大多数基本数据结构。因此,我会将您发送的数据保存到更简单的 Python 对象中,例如字符串、列表、字典等。
    • 感谢您的回答。正如你所提到的,一旦我传递了一个 PyQt5 对象,它就会给我一个错误。问题是我想在多处理函数执行过程中反映进度条的变化,所以我需要将它作为参数传递。您这样做的方式是仅在多处理期间操纵百分比,但这在处理完成之前不会反映在实际进度条上。我对么?
    • 不,我的回答是建议你这样做:启动你的多进程。在该多进程中,使用多进程队列向主线程发送可用于计算进度百分比的信息。在带有计时器的主线程中,检查多进程队列以获取该信息,并在有数据时更新进度条
    • 您还可以使用信号和插槽而不是计时器来实现更快的 CPU 密集型更新。
    • 现在我得到了你,我会尝试并更新你的结果,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-16
    • 2017-07-17
    • 2018-10-13
    • 2012-01-26
    相关资源
    最近更新 更多