在python多处理加速功能(Multiprocessing in python to speed

2019-07-31 04:20发布

我很困惑与Python多。

我试图加快功能,工艺字符串从数据库中,但我一定是误解了怎么多的作品,因为当给工人比“正常处理”一池的功能,需要更长的时间。

这里我想实现的例子。

from time import clock, time
from multiprocessing import Pool, freeze_support

from random import choice


def foo(x):
    TupWerteMany = []
    for i in range(0,len(x)):
         TupWerte = []
          s = list(x[i][3])
          NewValue = choice(s)+choice(s)+choice(s)+choice(s)
          TupWerte.append(NewValue)
          TupWerte = tuple(TupWerte)

          TupWerteMany.append(TupWerte)
     return TupWerteMany



 if __name__ == '__main__':
     start_time = time()
     List = [(u'1', u'aa', u'Jacob', u'Emily'),
        (u'2', u'bb', u'Ethan', u'Kayla')]
     List1 = List*1000000

     # METHOD 1 : NORMAL (takes 20 seconds) 
     x2 = foo(List1)
     print x2[1:3]

     # METHOD 2 : APPLY_ASYNC (takes 28 seconds)
     #    pool = Pool(4)
     #    Werte = pool.apply_async(foo, args=(List1,))
     #    x2 = Werte.get()
     #    print '--------'
     #    print x2[1:3]
     #    print '--------'

     # METHOD 3: MAP (!! DOES NOT WORK !!)

     #    pool = Pool(4)
     #    Werte = pool.map(foo, args=(List1,))
     #    x2 = Werte.get()
     #    print '--------'
     #    print x2[1:3]
     #    print '--------'


     print 'Time Elaspse: ', time() - start_time

我的问题:

  1. 为什么apply_async需要更长的时间比“正常方式”?
  2. 我做错了什么地图?
  3. 是否是有意义的多处理都加快这些任务?
  4. 最后:所有我看过这里后,我想知道如果在Windows上多处理器在Python的作品呢?

Answer 1:

所以,你的第一个问题是,有没有实际的并行发生在foo(x) ,要传递整个列表的功能一次。

1)的处理池的想法是有许多工艺做了一些数据的单独的位计算。

 # METHOD 2 : APPLY_ASYNC
 jobs = 4
 size = len(List1)
 pool = Pool(4)
 results = []
 # split the list into 4 equally sized chunks and submit those to the pool
 heads = range(size/jobs, size, size/jobs) + [size]
 tails = range(0,size,size/jobs)
 for tail,head in zip(tails, heads):
      werte = pool.apply_async(foo, args=(List1[tail:head],))
      results.append(werte)

 pool.close()
 pool.join() # wait for the pool to be done

 for result in results:
      werte = result.get() # get the return value from the sub jobs

这只会给你一个实际的加速,如果所花费的时间来处理每块比它需要启动过程中,四个过程和四份工作的情况下进行,时间越大当然这些动态,如果你改变”已经有4个进程和100个作业来完成。 请记住,你正在创建一个全新的Python解释器的四倍,这不是免费的。

2)你有地图的问题是,它适用foo在每一个元素List1在一个单独的进程,这将需要相当一段时间。 所以,如果你是池有4个进程map会弹出列表中的项目四次并将其发送到一个进程要处理-等待进程结束-弹出列表中的一些更多的东西-等待进程结束。 这是有道理的,如果只处理一个项目需要很长的时间,例如像如果每一个项目是文件名指向一个千兆字节的文本文件。 但是,因为它代表的地图将只取列表的一个字符串,并把它传递给foo地方作为apply_async采取列表的片段。 试试下面的代码

def foo(thing):
    print thing

map(foo, ['a','b','c','d'])

这是内置的蟒蛇地图和运行一个单一的过程,但这个想法是完全针对多进程的版本相同。

新增按JFSebastian的评论:但是,您可以使用chunksize参数map到指定的近似尺寸为每个块。

pool.map(foo, List1, chunksize=size/jobs) 

我不知道但如果有一个问题map上的Windows,因为我没有一个可用于测试。

3)是的,因为你的问题是大到足以证明分叉新Python解释

4)不能给你一个明确的答案,因为它取决于内核/处理器数量等,但一般应该是在Windows的罚款。



Answer 2:

关于问题(2)随着杜格尔和马蒂的指导下,我想通了什么地方出了错。 原始FOO函数处理列表的列表,而地图需要一个函数来处理单一的元件。

新的功能应该是

def foo2 (x):
    TupWerte = []
    s = list(x[3])
    NewValue = choice(s)+choice(s)+choice(s)+choice(s)
    TupWerte.append(NewValue)
    TupWerte = tuple(TupWerte)
    return TupWerte

和块来调用它:

jobs = 4
size = len(List1)
pool = Pool()
#Werte = pool.map(foo2, List1, chunksize=size/jobs)
Werte = pool.map(foo2, List1)
pool.close()
print Werte[1:3]

感谢大家谁帮助我理解这一点。

的所有方法的结果:表2 *宇记录:正常13.3秒,平行异步7.5秒,平行与地图chuncksize:7.3,无CHUNKSIZE5.2秒



Answer 3:

这里有一个通用的多模板,如果你有兴趣。

import multiprocessing as mp
import time

def worker(x):
    time.sleep(0.2)
    print "x= %s, x squared = %s" % (x, x*x)
    return x*x

def apply_async():
    pool = mp.Pool()
    for i in range(100):
        pool.apply_async(worker, args = (i, ))
    pool.close()
    pool.join()

if __name__ == '__main__':
    apply_async()

和输出看起来是这样的:

x= 0, x squared = 0
x= 1, x squared = 1
x= 2, x squared = 4
x= 3, x squared = 9
x= 4, x squared = 16
x= 6, x squared = 36
x= 5, x squared = 25
x= 7, x squared = 49
x= 8, x squared = 64
x= 10, x squared = 100
x= 11, x squared = 121
x= 9, x squared = 81
x= 12, x squared = 144

正如你所看到的,数字不按顺序排列,因为他们正在异步执行。



文章来源: Multiprocessing in python to speed up functions