Python多处理-如何提高效率

时间:2019-03-17 20:54:27

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

请考虑以下两个简短程序。

normal_test.py

import time

if __name__ == '__main__':
    t_end = time.time() + 1
    loop_iterations = 0
    while time.time() < t_end:
        loop_iterations += 1

    print(loop_iterations)

输出(在我的计算机上):

4900677

mp_test.py

from multiprocessing import Process
from multiprocessing import Manager
import time


def loop1(ns):
    t_end = time.time() + 1
    while time.time() < t_end:
        ns.loop_iterations1 += 1


def loop2(ns):
    t_end = time.time() + 1
    while time.time() < t_end:
        ns.loop_iterations2 += 1


if __name__ == '__main__':
    manager = Manager()
    ns = manager.Namespace()
    ns.loop_iterations1 = 0
    ns.loop_iterations2 = 0

    p1 = Process(target=loop1, args=(ns,))
    p2 = Process(target=loop2, args=(ns,))
    p1.start()
    p2.start()

    p1.join()
    p2.join()

    print(ns.loop_iterations1)
    print(ns.loop_iterations2)

输出(在我的计算机上):

5533
5527

我希望在Raspberry Pi上使用Python多处理,以并行地从多个ADC读取值。因此,速度很重要。我在这两个程序上运行的笔记本电脑有四个内核,所以我不明白为什么第二个程序中创建的进程只能比第一个程序中的单个进程运行近900倍的迭代。我是否在错误地使用Python多处理库?如何使流程更快?

2 个答案:

答案 0 :(得分:2)

  

我不正确地使用Python多处理库吗?

不正确?不,效率低下吗?是的。

请记住,多处理会创建协作的但独立的Python实例。可以将他们想象成工厂的工人,还是从事大工作的朋友。

如果只有个人在从事项目工作,那么一个人可以自由地在工厂车间移动,拿起工具,使用工具,放下工具,在其他地方移动,拿起工具下一个工具,依此类推。再增加一个人(或更糟的是,更多的人,甚至数百人),并且该人现在必须进行协调:如果某个区域是共享的,或者某个工具是共享的,则Bob不能只是去抢东西,他必须问Alice首先,如果她做完了。

"size":"0"对象是Python多处理程序的通用包装器,用于共享。将变量放入管理器Manager意味着这些变量是共享的,因此在使用它们之前会自动与其他所有人进行核对。 (更确切地说,它们被保存在一个位置,一个过程中,并且可以通过代理进行访问或更改)。

在这里,您已经做了比喻的等效操作,将“鲍勃:尽可能快地计数”替换为“鲍勃:不断打扰爱丽丝,问她是否在计数,然后再计数;爱丽丝:计数,但不断被鲍勃打断。 ”到目前为止,鲍勃和爱丽丝在彼此交谈上花费的时间最多,而不是数数。

the documentation says

  

...在进行并发编程时,通常最好尽可能避免使用共享状态。使用多个进程时尤其如此。

(以“如上所述”开头,但上面没有提到!)。

有很多标准技巧,例如 batching 可以在共享事件之间完成很多工作,或者使用共享内存为加快共享速度-但是通过共享内存,您需要锁定项目。

答案 1 :(得分:0)

通过多处理Queue,看起来是实现并行处理(不需要共享状态时)的更好方法。 OP的两个循环不需要共享状态。

这是测试。

规格:

  • Python版本:3.7.6。
  • 机器具有2.3 GHz的两个Intel i-9 9880H CPU。

当我在问题中执行normal_test.py时,我得到了:

$ python normal_test.py
7601322

然后我按如下所示测试了多处理Queue(两个并行进程):

import time
from multiprocessing import Process, Queue


def loop(n, q):
    n_iter = 0
    t_end = time.time() + 1
    while time.time() < t_end:
        n_iter += 1
    q.put((n, n_iter))


if __name__ == '__main__':
    results = []

    q = Queue()
    procs = []
    for i in range(2):
        procs.append(Process(target=loop, args=(i, q)))

    for proc in procs:
        proc.start()

    for proc in procs:
        n, loop_count = q.get()
        results.append((n, loop_count))

    for proc in procs:
        proc.join()

    del procs, q

    for r in results:
        print(r)

执行此操作时,我得到了:

$ python multiproc2.py
(1, 10570043)
(0, 10580648)

似乎并行运行两个进程比仅运行一个进程能做更多的工作。