Python2.7 中的多处理

Multiprocessing in Python2.7

在我开始将 "multiprocessing" 模块应用到我的主要代码之前,我试图通过示例更多地了解它,并且我对这段代码中的执行顺序有点困惑。

代码:

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. 根据上面的代码和时间应该是这个顺序?

广场开始于:
多维数据集开始于:
平方结束于:
多维数据集结束于:
在 p1.join() 之后:
方形 + 立方体:

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

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

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

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() 或更好的东西,一个高性能计数器来正确跟踪实时。