簡體   English   中英

多重處理池和速率限制

[英]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

更新2

我發現像這樣的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.

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