【问题标题】:Multiprocessing in Python. Why is there no speed-up?Python中的多处理。为什么没有加速?
【发布时间】:2015-10-15 00:05:39
【问题描述】:

我正在尝试掌握 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”。

【问题讨论】:

  • 尊敬的先生,谢谢。我以前读过这个 GIL。我认为使用多处理(正如我在这里所做的那样,我相信)可以解决这个问题。我原本打算使用 OpenMP,但发现由于 GIL,这在 Python 中是不可能的。我猜 Python 并不是为高速并行任务而构建的。
  • 感谢您的提醒,看来您是对的。从文档中,multiprocessing“通过使用子进程而不是线程来有效地避开全局解释器锁”。说得通。所以无视我之前的评论。

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


【解决方案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 编写的昂贵函数并且已经并行化,因此您无法做任何事情来加速它们。

【讨论】:

  • 非常感谢。首先,当我修复这个错误时,我发现所用的时间有所不同。我现在明白,使用多个进程只能用于昂贵的计算。 numpy 和 scipy 操作是否自动并行化?那么,如果我对一个数组应用一个numpy函数或者用一个大数组进行计算,它会自动并行化吗?
  • 这取决于你使用的函数,并不是所有的都是并行的,但大多数numpy的数组操作都是并行的。您应该查看您感兴趣的函数的文档,以检查它们是否被并行化。如果该函数是并行化的,则您无需做任何事情来改进它(无论如何在 Python 中)
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    您的工作似乎是计算单个 cos 值。与与从机通信的时间相比,这将基本不明显。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-30
      • 2021-03-16
      • 1970-01-01
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-01
      相关资源
      最近更新 更多