[英]multiprocessing.Pool and Rate limit
我正在發出一些API請求,這些請求限制為每秒20個。 為了得到答案,等待時間約為0.5秒,我以為使用multiprocessing.Pool.map並使用此裝飾器限速,所以我的代碼看起來像
def fun(vec):
#do stuff
def RateLimited(maxPerSecond):
minInterval = 1.0 / float(maxPerSecond)
def decorate(func):
lastTimeCalled = [0.0]
def rateLimitedFunction(*args,**kargs):
elapsed = time.clock() - lastTimeCalled[0]
leftToWait = minInterval - elapsed
if leftToWait>0:
time.sleep(leftToWait)
ret = func(*args,**kargs)
lastTimeCalled[0] = time.clock()
return ret
return rateLimitedFunction
return decorate
@RateLimited(20)
def multi(vec):
p = Pool(5)
return p.map(f, vec)
我有4個核心,該程序運行良好,與循環版本相比,時間有所改善。 此外,當Pool參數為4,5,6時,它可以工作,而Pool(6)的時間更短,但是當我使用7+時,會出現錯誤(我猜每秒連接太多)。
然后,如果我的函數更復雜並且可以執行1-5請求,則裝飾器將無法正常工作。 在這種情況下,我還能使用什么?
對於任何想要使用的人,Pool都記得要關閉它,否則您將使用所有RAM
def multi(vec):
p = Pool(5)
res=p.map(f, vec)
p.close()
return res
我發現像這樣的WebRequestManager可以解決問題。 問題在於不適用於多處理。 具有19-20個進程的池,因為時間存儲在運行請求時需要調用的類中。
上方的縮進不一致,因此很難回答,但我會采取措施。
看來您正在限制錯誤的事情; 如果應該限制f
則需要將調用限制為f
,而不是對multi
的調用。 在派遣到Pool
事務中執行此操作將不起作用,因為分叉的工作人員將各自獨立地進行限制(分叉的進程將獨立跟蹤自上次調用以來的時間)。
最簡單的方法是限制Pool
從中拉出的迭代器產生結果的速度。 例如:
import collections
import time
def rate_limited_iterator(iterable, limit_per_second):
# Initially, we can run immediately limit times
runats = collections.deque([time.time()] * limit_per_second)
for x in iterable:
runat, now = runats.popleft(), time.time()
if now < runat:
time.sleep(runat - now)
runats.append(time.time() + 1)
yield x
def multi(vec):
p = Pool(5)
return p.map(f, rate_limited_iterator(vec, 20))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.