在Windows中(但在Linux中),多处理比串行处理要慢

时间:2018-09-23 10:32:49

标签: python multithreading parallel-processing multiprocessing python-multiprocessing

由于循环处理操作都是独立的,因此我试图并行化for loop来加快我的代码的速度。遵循在线教程之后,看来Python中的标准multiprocessing库是一个好的开始,而我已经将其用于基本示例。

但是,对于我的实际用例,我发现在Windows上运行时,并行处理(使用双核计算机)实际上要慢一点(<5%)。但是,与串行执行相比,在Linux上运行相同的代码可以使并行处理速度提高约25%。

从文档中,我认为这可能与Window缺少fork()函数有关,这意味着每次都需要重新初始化该过程。但是,我对此并不完全了解,想知道是否有人可以确认这一点?

特别是

->这是否意味着要在Windows上为每个并行进程运行调用python文件中的所有代码,甚至初始化类和导入包?

->如果是这样,可以通过某种方式将类的副本(例如使用Deepcopy)传递到新进程中来避免这种情况吗?

->是否有任何技巧/其他策略可以有效地并行处理UNIX和Windows的代码设计。

我的确切代码很长,并且使用许多文件,因此我创建了一个pseucode样式的示例结构,希望可以显示此问题。

# Imports
from my_package import MyClass
imports many other packages / functions

# Initialization (instantiate class and call slow functions that get it ready for processing)
my_class = Class()
my_class.set_up(input1=1, input2=2)

# Define main processing function to be used in loop
def calculation(_input_data):
    # Perform some functions on _input_data
    ......
    # Call method of instantiate class to act on data
    return my_class.class_func(_input_data)

input_data = np.linspace(0, 1, 50)
output_data = np.zeros_like(input_data)

# For Loop (SERIAL implementation)
for i, x in enumerate(input_data):
    output_data[i] = calculation(x)

# PARALLEL implementation (this doesn't work well!)
with multiprocessing.Pool(processes=4) as pool:
    results = pool.map_async(calculation, input_data)
    results.wait()
output_data = results.get()

编辑:我不认为该问题与所建议的重复,因为这与Windows和Linunx的差异有关,在所建议的重复问题中根本没有提及。

1 个答案:

答案 0 :(得分:4)

NT操作系统缺少UNIX fork原语。创建新进程后,它将作为空白进程开始。家长有责任指导如何引导的新过程。

Python multiprocessing API抽象化了流程创建过程,试图使forkforkserverspawn启动方法具有相同的感觉。

使用spawn启动方法时,这就是幕后发生的事情。

  1. 创建了空白进程
  2. 空白过程将启动一个全新的Python解释器
  3. 通过Process类初始化程序指定的MFA(模块函数参数)被赋予了Python解释器
  4. Python解释器会加载给定的模块,以解决所有导入问题
  5. 在模块中查找target函数,并使用给定的argskwargs
  6. 进行调用

以上流程几乎没有影响。

您已经注意到自己,与fork相比,这是一项更加繁重的操作。这就是为什么您会注意到性能上的差异。

在子进程中从头开始导入模块时,所有导入副作用都会重新执行。这意味着常量global variablesdecorators和一级指令将再次执行。

另一方面,在父进程执行过程中进行的初始化不会传播到子进程。请参见this示例。

这就是为什么他们在multiprocessing文档中的Programming Guidelines中添加了Windows的特定段落。我强烈建议您阅读《编程指南》,因为它们已经包含了编写可移植的多处理代码所需的所有信息。