首页 > 解决方案 > Python2.7中的多处理

问题描述

在开始将“多处理”模块应用到我的主代码之前,我试图通过示例更多地了解它,并且我对此代码中的执行顺序感到困惑。

编码 :

import multiprocessing as mp
import time
import os

def square( nums , r , t1 ) :
    print ("square started at :")
    print ("%.6f" % (time.clock()-t1))
    for n in nums :
        r.append(n*n)
    print ("square endeded at :")
    print ("%.6f" % (time.clock()-t1))

def cube ( nums , r , t1 ) :
    #time.sleep(2)
    print ("cube started at   :")
    print ("%.6f" % (time.clock()-t1))
    for n in nums :
        r.append(n*n*n)
    print ("cube endeded at   :")
    print ("%.6f" % (time.clock()-t1))


if __name__ == "__main__" :
    numbers = range(1,1000000)
    results1 = []
    results2 = []
    t1 = time.clock()

    # With multiprocessing :
    p1 = mp.Process(target = square , args = (numbers , results1 , t1))
    p2 = mp.Process(target = cube   , args = (numbers , results2 , t1))
    p1.start()
    #time.sleep(2)
    p2.start()
    p1.join()
    print ("After p1.join()   :")
    print ("%.6f" % (time.clock()-t1))
    p2.join()

    '''
    # Without multiprocessing :
    square(numbers , results1 ,t1)
    cube(numbers , results2 , t1)

    '''
    print ("square + cube :")
    print ("%.6f" % (time.clock()-t1))

代码输出是:

square started at :  
0.000000  
square endeded at :  
0.637105  
After p1.join()   :  
12.310289  
cube started at   :  
0.000000  
cube endeded at   :  
0.730428  
square + cube :  
13.057885

我有几个问题:

  1. 根据上面的代码和时间应该是这个顺序吗?

square started at :
cube started at :
square endeded at :
cube endeded at :
After p1.join() :
square + cube :

  1. 为什么程序需要很长时间才能到达 (p1.join()) 尽管它在几秒钟前完成了“正方形”?
    换句话说,为什么正方形和立方体需要大约 13 秒才能运行,而实时执行时间是 0.7 秒!

  2. 在我的主代码中,我想在第一个函数延迟一秒后启动第二个函数(在这个例子中是立方体),所以我试图在“p1.start()”之间放置一个延迟(time.sleep(1)) ”和“p2.start()”但它不起作用,两个函数仍然从(0.000000s)开始,然后我把延迟放在“立方体”函数的开头,它也不起作用,所以我的问题是如何实现这两个功能之间的延迟?

标签: pythonmultiprocessingpython-multiprocessing

解决方案


在处理多线程时,各种其他因素都会影响您所看到的。由于您实际上是在向操作系统的进程管理器添加子进程,因此它们将完全独立于您正在运行的程序运行,包括拥有自己的资源、调度优先级、管道等。

1.)不。原因是每个子进程都有自己的输出缓冲区,它正在写入该缓冲区,然后再写回父进程。由于您启动了两个子进程,然后告诉父进程阻塞线程直到子进程 p1 完成,所以 p2 子进程在 p1 进程完成之前无法将其缓冲区写入父进程。这就是为什么尽管等待了 12 秒,p2 进程的输出仍然显示 0.7 秒。

2.) 很难确定为什么子进程运行它需要 12 秒。它可能是您的代码中的某些内容,也可能是其他十几个原因,例如一个完全不同的进程在一段时间内劫持了您的 CPU。首先,如果您尝试测量实际时间与进程在 CPU 上花费的时间,那么 time.clock 可能不是您想要的。其他评论者正确地建议使用高性能计数器来准确跟踪时间,以确保您测量时间的方式没有任何奇怪之处。此外,在启动、运行和终止一个新进程时,总会有一定程度的开销,尽管肯定不是 12 秒。确定这 12 秒是否可以控制的最佳方法是多次运行应用程序并查看总的结果时间是否存在很大差异。如果有,可能是与运行它的计算机有关的其他条件。

3.)我猜问题是 time.clock 测量。time.clock 调用计算进程在 CPU 上花费的时间。由于您正在使用多个进程,因此启动进程时 time.clock 将重置为 0。这是一个相对时间,而不是绝对时间,并且相对于过程的生命周期。如果您在进程或休眠线程之间跳转, time.clock 不一定会增加您对绝对时间测量的思考方式。您应该使用类似 time.time() 或更好的东西,一个高性能计数器来正确跟踪实时。


推荐阅读