【问题标题】:ipython parallel client.map dramatically slower than python "map"?ipython并行client.map比python“map”慢得多?
【发布时间】:2015-05-05 20:54:28
【问题描述】:

我试图了解为什么我的负载平衡视图映射语句需要 22 秒才能在 2 个内核上执行,而不是使用内置映射在一个内核上只需 10 毫秒。我知道并行工作有与之相关的开销,但这无法解释额外的 22 秒。我究竟做错了什么?

我在 Intel Core2Duo Mac 上运行 Python 2.7。操作系统 X.10。

In [4]: from IPython.parallel import Client

In [5]: rc = Client()

In [6]: lview = rc.load_balanced_view()

In [7]: lview.block = True

In [8]: %timeit map(lambda x:x**10, range(3000))
100 loops, best of 3: 9.91 ms per loop

In [9]: %timeit lview.map(lambda x:x**10, range(3000))
1 loops, best of 3: 22.8 s per loop

【问题讨论】:

    标签: python parallel-processing ipython


    【解决方案1】:

    只是有很多的开销。您必须通过消息队列将作业发送给工作人员为您执行的每个循环。如果你更聪明地分配你的工作,它会更有效率(但仍然不如单线程版本那么高效):

    In [7]: %timeit map(lambda x:x**10, range(3000))
    100 loops, best of 3: 3.17 ms per loop
    
    In [8]: %timeit lview.map(lambda i:[x**10 for x in range(i * 500)], range(6))  # I'm using 6 cores
    100 loops, best of 3: 11.4 ms per loop
    
    In [9]: %timeit lview.map(lambda i:[x**10 for x in range(i * 1500)], range(2))
    100 loops, best of 3: 5.76 ms per loop
    

    如果您的工作量足够大,并行化就会得到回报:

    In [10]: %timeit lview.map(lambda i:len([x**10 for x in range(i * 500000)]), range(6))
    1 loops, best of 3: 2.86 s per loop
    
    In [11]: %timeit map(lambda x:x**10, range(3000000))
    1 loops, best of 3: 3.41 s per loop
    

    【讨论】:

    • 可以改用LoadBalancedViewchunksize参数:lview.map(lambda x: x**10, range(10000), chunksize=2000)
    【解决方案2】:

    正如 univerio 所指出的,存在大量开销。使用非常快的任务测试 IPython.parallel 会导致性能不佳。您的任务几乎不需要时间就可以完成,甚至比简单的开销还要简单。另一方面,如果每个任务需要一秒钟才能完成,IPython.parallel 会更有用。请记住,该系统不仅设计用于跨多个内核分配任务,而且还跨多台可能具有非常不同环境、未运行预共享代码且不一定具有共享内存或磁盘的计算机。我过去有一个控制器,在不同城市的多台计算机上运行不同的 Python 版本和不同的操作系统,将任务分配到 300 个 CPU。所有这些都需要相当多的开销。例如,当您发送任务时,您就是在发送任务所需的代码和数据。

    然而,另一个问题是,IPython 的并行系统需要针对您提供给它的各种任务进行配置。特别是,ipcontroller 配置中的高水位线 (HWM) 设置对较小任务的性能有显着影响。默认情况下,HWM 设置为 1,这意味着控制器向每个 ipengine worker 发送一个任务,并且在第一个任务返回给它之前不会向该 worker 发送新任务。这实现了最好的负载平衡,因为这意味着如果任务花费不同的时间,那么工作人员每次完成他们正在处理的任务时都会获得一个新任务,而更快的工作人员将获得更多的任务。在某些情况下,这可能非常很慢。

    但是,如果您的任务很快,则意味着开销要大得多。在这些情况下,将 HWM 设置为更高的值会很有用。 HWM 本质上是一个引擎上允许有多少任务未完成的设置。将其设置为 10,控制器将向每个引擎发送 10 个任务,然后在引擎低于 10 个未完成任务时(单独)发送新任务。

    对于大量非常快的任务,一个特别有用的设置是特殊设置 0。在这种情况下,控制器将所有任务一次性分发给工作人员,然后等待他们返回。

    这个设置是 ipcontroller_config.py 中的 c.TaskScheduler.hwm。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-12
      • 2020-03-01
      • 1970-01-01
      • 2017-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多