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