首页 > 解决方案 > Python 多处理 - 如何使其更高效

问题描述

考虑以下两个短程序。

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 多处理库?如何使流程更快?

标签: pythonpython-3.xperformancemultiprocessingpython-multiprocessing

解决方案


我是否错误地使用了 Python 多处理库?

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

请记住,多处理会创建协作但独立的 Python 实例。把他们想象成工厂的工人,或者做一份大工作的朋友。

如果只有一个人在做一个项目,那么这个人可以在工厂车间自由走动,拿起一个工具,使用它,放下它,移动到其他地方,拿起下一个工具,等等。添加第二个人——或者更糟,更多人,甚至数百人——并且这个人现在必须协调:如果某个区域是共享的,或者某个工具是共享的,Bob 不能随便去拿东西,他必须问 Alice首先,如果她完成了。

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

在这里,您已经完成了将“Bob:尽可能快地数数”替换为“Bob:不断打断 Alice 询问她是否在数数,然后数数;Alice:数数,但不断被 Bob 打断”的隐喻等效。到目前为止,鲍勃和爱丽丝大部分时间都花在了彼此交谈上,而不是数数上。

正如文档所说

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

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

有许多标准技巧,例如在共享事件之间进行批处理以完成大量工作,或者使用共享内存来加速共享——但是使用共享内存,您需要锁定项目。


推荐阅读