簡體   English   中英

python中的多處理以加速功能

[英]Multiprocessing in python to speed up functions

我對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. 最后:畢竟我在這里讀過,我想知道python中的多處理是否適用於Windows?

所以你的第一個問題是在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)你對map有的問題是它在一個單獨的進程中將foo應用於List1中的每個元素,這將花費很長時間。 因此,如果你的游泳池有4個進程map將彈出列表中的項目四次並將其發送到要處理的進程 - 等待進程完成 - 彈出更多的列表內容 - 等待進程完成。 這僅在處理單個項目需要很長時間時才有意義,例如,如果每個項目都是指向一個千兆字節文本文件的文件名。 但是,當它站在map時,只需要獲取列表中的單個字符串並將其傳遞給foo ,其中apply_async將獲取列表的一部分。 請嘗試以下代碼

def foo(thing):
    print thing

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

這是內置的python映射,將運行單個進程,但多進程版本的想法完全相同。

根據JFSebastian的評論添加:但是您可以使用chunksize參數進行map以指定每個塊的大致大小。

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

我不知道在Windows上是否存在map問題,因為我沒有可用於測試的地圖。

3)是的,因為你的問題足夠大,足以證明你可能需要新的python解釋器

4)無法給出明確的答案,因為它取決於核心/處理器的數量等,但一般情況下它應該在Windows上正常。

問題(2)在Dougal和Matti的指導下,我弄清楚出了什么問題。 原始foo函數處理列表列表,而map需要一個函數來處理單個元素。

新功能應該是

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]

感謝所有幫助我理解這一點的人。

所有方法的結果:對於List * 2 Mio記錄:正常13.3秒,與異步並行:7.5秒,與具有chuncksize的地圖並行:7.3,沒有chunksize 5.2秒

如果您有興趣,這是一個通用的多處理模板。

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

如您所見,數字不是有序的,因為它們是異步執行的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM