使用多重处理在类方法的while循环内运行函数

时间:2020-09-05 08:12:33

标签: python parallel-processing multiprocessing

我有一种方法可以使用多种其他方法来计算最终结果。它具有一个while循环,该循环中不断检查新数据,如果接收到新数据,它将运行其他方法并计算结果。该主要方法是用户调用的唯一方法,并且在关闭程序之前一直保持活动状态。基本结构如下:

@Component({
    selector: "app-foo",
    templateUrl: "./foo.component.html",
    styleUrls: ["./foo.component.scss"]
})
export class FooComponent extends BaseComponent implements OnInit, OnDestroy {

    ngOnInit(): void {
        this.store.dispatch(ApplicationFooItemsRequestedAction());
        this.fooList$ = this.store.select(selectAllApplicationFooItems);

        this.fooList$.pipe(takeUntil(untilDestroyed(this))).subscribe(ul => {
             // do stuff with items
        });
     }

}

我想并行运行calc1和calc2,以便可以更快地获得最终结果。但是,由于我没有使用class sample: def __init__(self): results = [] def main_calculation(self): while True: #code to get data if newdata != olddata: #insert code to prepare data for analysis res1 = self.calc1(prepped_data) res2 = self.calc2(prepped_data) final = res1 + res2 self.results.append(final) 保护,因此我不确定如何以这种方式实现多重处理。有什么办法可以并行运行这些进程?

这可能不是此代码的最佳组织,但是对于我正在运行的实际计算而言,这是最简单的方法,因为有必要将此代码导入并从其他文件运行。但是,如果这不是一种可挽救的结构,我可以重组代码。

1 个答案:

答案 0 :(得分:1)

根据the documentation,您需要使用__main__保护的原因是,当程序创建multiprocessing.Process对象时,它将启动Python解释器的全新副本,将导入程序模块的新副本。如果导入模块本身调用multiprocessing.Process(),则将创建Python解释器的另一个副本,该副本解释代码的另一个副本,依此类推,直到系统崩溃(或实际上,直到Python遇到不可重入的片段为止)多处理代码)。

在程序的主模块(通常会在顶层调用某些代码)中,检查__name__ == '__main__'是您判断程序是首次运行还是作为子进程运行的方式。但是在不同的模块中,顶层可能没有任何代码(定义除外),在这种情况下,无需使用防护,因为可以安全地导入模块而无需启动新进程。

换句话说,这很危险:

import multiprocessing as mp

def f():
    ...

p = mp.Process(target=f)
p.start()
p.join()

但这很安全:

import multiprocessing as mp

def f():
    ...

def g():
    p = mp.Process(target=f)
    p.start()
    p.join()

这也是安全的:

import multiprocessing as mp

def f():
    ...

class H:
    def g(self):
        p = mp.Process(target=f)
        p.start()
        p.join()

因此在您的示例中,您应该能够直接在函数中创建Process对象。

但是,我建议在类的文档中明确指出该方法创建了Process,因为无论使用它的人(也许您)都需要知道在该方法处调用该方法并不安全。模块的顶层。就像这样做,它也属于“危险”类别:

import multiprocessing as mp

def f():
    ...

class H:
    def g(self):
        p = mp.Process(target=f)
        p.start()
        p.join()

H().g()  # this creates a Process at the top level

您还可以考虑使用另一种方法,使调用者完成所有流程的创建。在这种方法中,您的sample类构造函数或main_calculation()方法都可以接受一个Pool对象,并且可以使用该池中的进程进行计算。例如:

class sample:
    def main_calculation(self, pool):
        while True:
            if newdata != olddata:
                res1_async = pool.apply_async(self.calc1, [prepped_data])
                res2_async = pool.apply_async(self.calc2, [prepped_data])
                res1 = res1_async.get()
                res2 = res2_async.get()
                # and so on

如果发生许多不同的计算,此模式还可以使您的程序更有效地利用资源,因为它们都可以使用相同的进程池。