首页 > 解决方案 > Python多处理代码比单线程运行慢

问题描述

我的 i7 7700HQ 上的 Python 多处理性能明显低于非并行处理性能。

在计划在 mssql 中为我的单表数据库并行化我的 Select 和 Update 代码时,我尝试首先并行化一个简单的代码。该程序只是打印参数的倍数。我尝试了使用 Process 对象和 Pool 对象的单线程、多进程。单线程总是表现最好。

import time

def foobar(a):
    for i in range(1,10000):
        print(a*i)
    return
if __name__ == "__main__":
   Tthreading = time.clock()
    p1= Process(target= foobar, args=(3,))
    p2 = Process(target= foobar, args= (2,))
    p3 = Process(target= foobar, args= (4,))
    p4 = Process(target=foobar, args=(123,))

    allprocess.start

    allprocess.join

    print(time.clock() - Tthreading)

    #Single-threaded
    Tsingle = time.clock()
    foobar(3)
    foobar(2)
    foobar(4)
    foobar(123)
    print(time.clock() - Tsingle)


我希望多进程更快,因为没有共享资源(没有函数,需要在线程之间访问的变量)和 IPC。

单线程时间:0.32s

多进程时间:0.53s

标签: pythonpython-3.xmultiprocessingpython-multiprocessingpymssql

解决方案


实际上,您的示例中有一个重要的共享资源,即您的监视器(或stdout)。

print是一个相对较慢的操作(与 CPU 周期相比......),它会导致您的进程之间发生争用。

正确地对并行工作进行基准测试是一项艰巨的任务,它受到 CPU 的许多因素和特性(例如缓存)的影响。

尝试用非常适合多处理的工作负载替换您的工作负载(例如,在数组的不同部分并行工作,矩阵乘法......)

还有一件更重要的事情:催生新流程也需要时间,而且要让每个流程中完成的工作得到回报,就需要很重要。如果稍微增加循环的范围,差异应该有利于多进程版本:

import time
from multiprocessing import Process

def foobar(a):
    for i in range(1,10000000):
        a*i
    return

if __name__ == "__main__":
    Tthreading = time.time()
    p1= Process(target= foobar, args=(3,))
    p2 = Process(target= foobar, args= (2,))
    p3 = Process(target= foobar, args= (4,))
    p4 = Process(target=foobar, args=(123,))

    allprocess = [p1,p2,p3,p4]
    for p in allprocess:
        p.start()

    for p in allprocess:
        p.join()

    print(time.time() - Tthreading)

    #Single-threaded
    Tsingle = time.time()
    foobar(3)
    foobar(2)
    foobar(4)
    foobar(123)
    print(time.time() - Tsingle)

在我的机器上输出:

0.44509196281433105

1.3775699138641357


推荐阅读