Python 如何在不使用所有工作人员的情况下限制大量任务

Python 如何在不使用所有工作人员的情况下限制大量任务,python,dask,Python,Dask,假设我有一个dask网格,共有10个工人和40个核心。这是一个共享的网格,所以我不想让我的工作完全浸透它。我有1000个任务要做,我想一次最多提交(并积极运行)20个任务 具体来说, from time import sleep from random import random def inc(x): from random import random sleep(random() * 2) return x + 1 def double(x): from

假设我有一个dask网格,共有10个工人和40个核心。这是一个共享的网格,所以我不想让我的工作完全浸透它。我有1000个任务要做,我想一次最多提交(并积极运行)20个任务

具体来说,

from time import sleep
from random import random

def inc(x):
    from random import random
    sleep(random() * 2)
    return x + 1

def double(x):
    from random import random
    sleep(random())
    return 2 * x

>>> from distributed import Executor
>>> e = Executor('127.0.0.1:8786')
>>> e
<Executor: scheduler=127.0.0.1:8786 workers=10 threads=40>
这会起作用,但是,这只会将我所有的任务转储到网格中,使其饱和。理想情况下,我可以:

e.scatter(input_q, max_submit=20)
文档中的示例似乎允许我使用
maxsize
队列。但从用户的角度来看,我仍然需要处理背压。理想情况下,
dask
会自动处理这个问题

使用
maxsize=
你很接近。所有
scatter
collect
map
都采用与
Queue
相同的
maxsize=
关键字参数。因此,一个简单的工作流可能如下所示:

例子 所有
q
futures
results
都是Python队列对象。
q
results
队列没有限制,因此它们会贪婪地尽可能多地加入。然而,
futures
队列的最大大小为20,因此它在任何给定时间只允许20个futures在飞行中。一旦前导期货完成,它将立即被gather函数使用,其结果将被放入
结果
队列。这会释放
futures
中的空间,并导致提交另一个任务

请注意,这并不是您想要的。这些队列是有序的,因此只有当它们位于队列前面时,才会弹出未来。如果所有的飞行中的期货都完成了,除了第一个,它们仍然会留在队列中,占据空间。考虑到这一限制,您可能希望选择比所需的
20
项稍多的
maxsize=

扩展这个
这里我们做一个简单的
map->gather
管道,中间没有逻辑。您还可以将其他
map
计算放在这里,甚至可以将期货从队列中取出,自己使用它们进行自定义工作。很容易打破上面提供的模式。

发布在github上的解决方案非常有用-

解决方案:

inputs = iter(inputs)
futures = [c.submit(func, next(inputs)) for i in range(maxsize)]
ac = as_completed(futures)

for finished_future in ac:
    # submit new future 
    try:
        new_future = c.submit(func, next(inputs))
        ac.append(new_future)
    except StopIteration:
        pass
    result = finished_future.result() 
    ... # do stuff with result
查询:

inputs = iter(inputs)
futures = [c.submit(func, next(inputs)) for i in range(maxsize)]
ac = as_completed(futures)

for finished_future in ac:
    # submit new future 
    try:
        new_future = c.submit(func, next(inputs))
        ac.append(new_future)
    except StopIteration:
        pass
    result = finished_future.result() 
    ... # do stuff with result
但是,为了确定可以自由限制任务的工作者,我尝试利用client.has_what()api。工作人员的负载似乎不会立即得到反映,与状态UI页面上显示的内容类似。有时,需要花费相当多的时间来确定要反映哪些数据


是否有其他api可用于确定自由工作人员的数量,然后可用于确定节流范围,类似于用户界面所使用的范围。

最好将解决方案代码复制/粘贴到答案中。我假设它是由mrocklin在那个问题线程中提供的答案。为人们寻找解决方案节省了时间,并使答案更加完整。@Lex-感谢您指出这一点,上面添加了解决方案。这是一个答案还是一个问题?这对我来说很好,但在最新版本的dask
ac.append
中变成了
ac.add
。还有一个
ac.update
,如果您需要的话,它允许您添加多个期货。
inputs = iter(inputs)
futures = [c.submit(func, next(inputs)) for i in range(maxsize)]
ac = as_completed(futures)

for finished_future in ac:
    # submit new future 
    try:
        new_future = c.submit(func, next(inputs))
        ac.append(new_future)
    except StopIteration:
        pass
    result = finished_future.result() 
    ... # do stuff with result