当进程计数和工作人员计数增加时,Python多处理池API无法有效工作

时间:2019-03-15 05:42:53

标签: python python-3.x multithreading multiprocessing python-multiprocessing

我正在尝试应用多重处理来并行化我的代码。我大约有 2000项作品要完成。由于创建2000个并发进程不切实际,因此我使用python multiprocessing.pool API在管理任务队列时并行化工作。我尝试创建100名工人。但是要花几个小时才能完成,与顺序实施相比,这并不是什么大的收获。我的笔记本电脑有12个逻辑核心。然后,我尝试同时增加工作人员和工作。从技术上讲,每项工作都需要花费相同的时间,因为我每次只将一项工作分配给一名工人。但是我发现即使每件工作的工作量不变,整个过程的时间也会增加。 API出问题了吗?还是我做错了?有人可以为我提供2000年使用Python在最短时间内进行并行处理的可行解决方案吗?

P.S:由于代码实现问题,我无法使用多线程。

我的代码

inputListLen = 13
workerCount = 13
regressList = regressList[:inputListLen] # regressList has 2000 items
with Pool(processes=workerCount) as pool:
    print(pool.map(runRegressWriteStatus, regressList))

结果

Input List Len  | workers   | Time(seconds) 
1               | 1         | 4.5  
2               | 2         | 4.9  
3               | 3         | 5.4  
4               | 4         | 5.6  
5               | 5         | 6.3  
6               | 6         | 7.2  
7               | 7         | 8.3  
8               | 8         | 9.6  
9               | 9         | 10.0 
10              | 10        | 10.7 
11              | 11        | 11.6 
12              | 12        | 11.8 
13              | 13        | 13.3 

1 个答案:

答案 0 :(得分:1)

我认为您误会了几件事,并且对几件事的假设并不是很准确。正如我在Python multiprocessing: dealing with 2000 processes中提到的那样,您实际上可以与multiprocessing并行运行的进程数取决于系统上具有的CPU核心数,并由它们控制。这是实际的物理核心,而不是启用超线程后看到的逻辑核心。

因此12个逻辑核心意味着6个物理核心,每个核心2个线程为您提供12个逻辑核心。因此,在任何时间点,您的内核都会看到12个逻辑内核,并尝试调度12个进程,但是系统只有6个物理内核,因此发生了很多上下文切换,使得它看起来好像有12个内核,但是在任何时间点实时不能超过6个进程,因为请记住您只有6个核心。

第二,Pool的工作方式不同于Process,而使用Process则可以启动并行进程来执行可能彼此独立的任务。

Pool具有不同的用途,使用Pool对象创建一个pool进程,然后将一个大任务/输入传递给它,然后将pool传递给它将这个大任务/输入分成较小的任务/输入,并将其分配到processes中,它们可以同时对较小的输入进行操作。

这是一个非常简单的示例,说明如何使用pool

import multiprocessing as mp
import time


def f(x):
    res = 0
    for i in range(x):
        res += i ** 6


if __name__ == '__main__':
    t1 = time.time()
    # MP Pool creates 4 concurrent processes and run the same function with diffrent args, to achieve the parallel computation
    po = mp.Pool(processes=4)
    res = po.map(f, range(5000))
    po.close()
    po.join()
    print('Parallel execution time taken = {}'.format(time.time() - t1))

    t2 = time.time()
    seq_res = list(map(f, range(5000)))
    print('Sequential execution time taken = {}'.format(time.time() - t2))

(py37) rbhanot@rbhanotlinux ~/home » python 7-1.mppool.py
Parallel execution time taken = 0.91422438621521
Sequential execution time taken = 2.9315543174743652
(py37) rbhanot@rbhanotlinux ~/home » 

如您所见,使用pool并行执行所花的时间比顺序执行所花的时间少3倍。

现在我有8个逻辑核心,但我的机器上只有4个物理核心,并且我的内核最多只能一次调度4个进程,因此创建一个包含4个以上进程的池不会有任何区别,这是一个证明。

与7个进程池一起运行时

Parallel execution time taken = 0.9177846908569336

在包含12个进程的池中运行

Parallel execution time taken =  0.9213907718658447

在包含2个进程的池中运行

Parallel execution time taken = 1.712911605834961