关于python:ThreadPool和Pool用于并行处理

ThreadPool and Pool for parallel processing

有没有一种方法可以通过指定要使用的CPU和内核数在python中同时使用ThreadPool和Pool来并行化循环?

例如,我将循环执行为:

1
2
3
4
5
6
7
8
9
10
11
12
from multiprocessing.dummy import Pool as ThreadPool
from tqdm import tqdm
import numpy as np

def my_function(x):
    return x + 1

pool = ThreadPool(4)
my_array = np.arange(0,1e6,1)


results = list(tqdm(pool.imap(my_function, my_array),total=len(my_array)))

对于4核,但我也想将它们分散到多个CPU上,是否有一种简单的方法来适应代码?


您在核心和CPU之间感到困惑。通常,出于所有目的,两者都被认为是相同的(从现在开始,我们称它们为处理器)。

在python中创建线程池时,由于python中的全局解释器锁(GIL),这些线程是用户级线程,并且在同一处理器上运行。由于一次只能有一个线程控制python解释器。因此,使用(python)线程在数据密集型任务中没有任何真正的并发性。

如何解决呢?简单。生成在不同处理器上运行的多个python进程(每个进程都有自己的解释器)。这是使用multi processing(mp)模块的地方,从调用它的父python进程中产生多个进程。

您可以通过运行htop(在linux,mac上)并分析python进程数来验证这一点。如果是mp模块,它们都将具有与调用pool.map函数的父脚本相同的名称。

  • 在8核心Mac上的代码计时:39.7秒
  • 在同一台机器上此代码的时间:2.9s(请注意,我最多可以使用8个核,但出于比较目的,仅使用4个核)

下面是修改后的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from multiprocessing.dummy import Pool as ThreadPool
from tqdm import tqdm
import numpy as np
import time
import multiprocessing as mp

def my_function(x):
    return x + 1

pool = ThreadPool(4)
my_array = np.arange(0,1e6,1)


t1 = time.time()
# results = list(tqdm(pool.imap(my_function, my_array),total=len(my_array)))
pool = mp.Pool(processes=4) # Generally, set to 2*num_cores you have
res = pool.map(my_function, my_array)
print("Time taken =", time.time() - t1)


multiprocessing.dummy.Pool完全是简单的ThreadPool,它不使用多核和multicpus(由于GIL)。您必须使用multiprocessing.Pool来运行进程,该进程是您操作系统中的进程(如果您定义Pool(N)-N是该进程的数量,如果没有定义-默认情况下,操作系统中的内核数量)。该过程的论据来自Pool的内部队列。 'U的情况将使用您操作系统中的所有CPU和所有内核