我在multiprocessing模块中尝试不同的启动方法,我发现了一些奇怪的东西。将变量
method
从 "spawn"
更改为 "fork"
,会将执行时间从 9.5
缩短至 0.5
。
import multiprocessing as mp
from multiprocessing import Process, Value
from time import time
def increment_value(shared_integer):
with shared_integer.get_lock():
shared_integer.value += 1
if __name__ == "__main__":
method = "spawn"
mp.set_start_method(method)
start = time()
for _ in range(200):
integer = Value("i", 0)
procs = [
Process(target=increment_value, args=(integer,)),
Process(target=increment_value, args=(integer,)),
]
for p in procs:
p.start()
for p in procs:
p.join()
assert integer.value == 2
print(f"{method} - Finished in {time() - start:.4f} seconds")
不同运行的输出:
spawn - Finished in 9.4275 seconds
fork - Finished in 0.5316 seconds
我知道这两种方法如何启动一个新的子进程(here有很好的解释),但这种差异在我的脑海中打了一个大问号。我想确切地知道代码的哪一部分对性能影响最大?这是
"spawn"
中的酸洗部分吗?和锁有关系吗?
我在 Linux Pop!_OS 上运行此代码,我的解释器版本是 3.11。
fork 方法复制进程中的所有资源并从该点继续,而 spawn 方法创建 Python 解释器的新实例并重新创建该点(“点”是指进程的状态:它拥有哪些资源,等)。
正如您可以想象的那样,简单地复制一些数据比创建全新的 Python 进程并重新创建所有数据的开销要少得多,因此速度要快得多。