我是多重处理新手,所以这可能是一个愚蠢的问题。
我使用的是 Ubuntu 20.04.6 LTS(64 位),配备第 12 代 Intel(R) Core(TM) i7-12700K 处理器和 16GB RAM,运行 Python 3.9.19。当我运行以下代码时,
htop
命令显示所有 10 个内核均按预期使用:
import time
def fun(ele):
ele ** 1000
if __name__ == '__main__':
import multiprocessing
input_list = [1000] * 10000000
start_time = time.time()
pool = multiprocessing.Pool(10)
result = pool.map(func=fun, iterable=input_list)
pool.close()
pool.join()
end_time = time.time()
print(end_time - start_time)
但是,当我导入一些额外的库(如
PIL
、numpy
等)时,即使创建了11个进程(1个主进程和10个子进程),似乎只有2个核心在工作。这是修改后的代码:
import time
from PIL import Image
import numpy as np
import pickle
import os
import torch
def fun(ele):
ele ** 1000
if __name__ == '__main__':
import multiprocessing
input_list = [1000] * 1000000
start_time = time.time()
pool = multiprocessing.Pool(10)
result = pool.map(func=fun, iterable=input_list)
pool.close()
pool.join()
end_time = time.time()
print(end_time - start_time)
使用命令
ps aux | grep [p]ython | grep $name_of_program$ | wc -l
,我确认确实创建了11个进程(1个主进程和10个子进程)。然而,这些进程似乎并未分布在所有 CPU 核心上。
用
spawn
将启动方式设置为multiprocessing.set_start_method('spawn')
后,所有10个核心再次正常工作。
import time
from PIL import Image
import numpy as np
import time
import numpy as np
from PIL import Image
import pickle
import os
import torch
def fun(ele):
ele**1000
if __name__ == '__main__':
import multiprocessing
multiprocessing.set_start_method('spawn')
input_list = [1000]*1000000
n = 250000
start_time = time.time()
pool = multiprocessing.Pool(10)
result = pool.map(func=fun, iterable=input_list)
pool.close()
pool.join()
end_time = time.time()
print(end_time-start_time)
为了测试您的计时,我建议您从可能使用多个 CPU 的最简单的代码开始。像这样的东西:
import time
import multiprocessing as mp
def fun(ele: int) -> int:
return ele * ele
if __name__ == "__main__":
start_time = time.time()
with mp.Pool() as pool:
pool.map_async(fun, range(250_000_000))
pool.close()
pool.join()
duration = time.time() - start_time
print(f"{duration=:.4f}s")
在 Apple M2 上,运行时间约为 35 秒 - 即有足够的时间运行 top 来查看发生了什么。
然后我会一一添加您的导入(即使您没有使用它们),看看哪些对您的观察影响最大。
注意:在 MacOS 上,“spawn”是默认值。从 start 方法的角度来看,您的观察很有趣,因为 fork (Linux 上的默认设置)通常被认为比 spawn 更快。所以你所看到的(对我来说)是反直觉的。