Python中的多处理。为什么没有加速?

时间:2015-07-24 10:42:02

标签: python python-3.x parallel-processing multiprocessing ipython

我正试图掌握Python中的多处理。我从创建此代码开始。它只是计算整数i的cos(i),并测量一个人使用多处理时和一个人不使用时的时间。我没有观察到任何时差。这是我的代码:

    import multiprocessing
    from multiprocessing import Pool
    import numpy as np
    import time


    def tester(num):
        return np.cos(num)


    if __name__ == '__main__':


        starttime1 = time.time()
        pool_size = multiprocessing.cpu_count()
        pool = multiprocessing.Pool(processes=pool_size,
                            )
        pool_outputs = pool.map(tester, range(5000000))
        pool.close()
        pool.join()
        endtime1 = time.time()    
        timetaken = endtime1 - starttime1  

        starttime2 = time.time()
        for i in range(5000000):
            tester(i)
        endtime2 = time.time()
        timetaken2 = timetaken = endtime2 - starttime2

        print( 'The time taken with multiple processes:', timetaken)
        print( 'The time taken the usual way:', timetaken2)

我观察到两次测量之间没有(或非常小的)差异。我正在使用8芯机器,所以这是令人惊讶的。我在代码中做错了什么?

请注意,我从中学到了所有这些。 http://pymotw.com/2/multiprocessing/communication.html

我理解" joblib"对于像这样的例子来说可能更方便,但是这个需要应用的最终事情不适用于" joblib"。

3 个答案:

答案 0 :(得分:7)

您的工作似乎是计算单个cos值。与与奴隶沟通的时间相比,这基本上是不明显的。

尝试对100个cos值进行5次计算,您应该看到它们并行运行。

答案 1 :(得分:1)

首先,你写道:

  

timetaken2 = timetaken = endtime2 - starttime2

如果您显示相同的时间,这是正常的。但这不是重要的部分。

我在我的电脑上运行了你的代码(i7,4核),我得到了:

  

('多个过程所花费的时间:',14.95710802078247)
  ('以通常的方式采取的时间:',6.465447902679443)

多处理循环比执行for循环慢。为什么呢?

multiprocessing模块可以使用多个进程,但仍然需要使用Python全局解释器锁,这意味着您无法在进程之间共享内存。因此,当您尝试启动Pool时,您需要复制有用的变量,处理计算并检索结果。这会花费您一点时间来处理每个过程,并使您的效率降低。

但他的发生是因为你做了一个非常小的计算:multiprocessing仅对更大的计算有用,当内存复制和结果检索比计算更便宜(及时)时。

在2000次试运行中,我尝试使用以下测试仪,价格要贵得多:

def expenser_tester(num):
    A=np.random.rand(10*num) # creation of a random Array 1D
    for k in range(0,len(A)-1): # some useless but costly operation
        A[k+1]=A[k]*A[k+1] 
    return A
  

('多个进程所花费的时间:',4.030329942703247)
  ('时间采用通常的方式:',8.180987119674683)

你可以看到,在昂贵的计算中,多处理效率更高,即使你并不总是拥有你所期望的(我可以有x4加速,但我只有x2) 请记住,Pool必须重复计算中使用的每一块内存,因此内存可能很昂贵。

如果你真的想要像你的例子一样改进一个小的计算,那么通过分组并将一个变量列表发送到池而不是一个变量来使其变大。

你还应该知道numpy和scipy有很多昂贵的函数用C / Fortran编写并且已经并行化了,所以你不能做任何事情来加速它们。

答案 2 :(得分:0)

如果问题是cpu限制,那么你应该看到所需的加速(如果操作足够长并且开销不重要)。但是当进行多处理时(因为进程之间没有共享内存),拥有memory bound problem会更容易。