为什么dask worker由于“小型”任务上的MemoryError而失败? [Dask.bag]

时间:2019-04-10 00:11:32

标签: dask dask-distributed

我正在多个图像上运行管道。管道包括从文件系统读取图像,对每个图像进行处理,然后将图像保存到文件系统。但是,由于MemoryError导致达不到工作的工作程序失败。 有没有办法确保敏捷工作者不会在内存中加载太多图像?即,等到工作人员上有足够的空间后,再开始对新映像进行处理。

我有一个调度程序和40个具有4个内核,15GB内存并运行Centos7的工人。我正在尝试批量处理125张图像;每个图像都很大,但足够小以适合工人。整个过程大约需要3GB。

我尝试处理少量图像,效果很好。

已编辑

from dask.distributed import Client, LocalCluster

# LocalCluster is used to show the config of the workers on the actual cluster
client = Client(LocalCluster(n_workers=2, resources={'process': 1}))

paths = ['list', 'of', 'paths']

# Read the file data from each path
data = client.map(read, path, resources={'process': 1)

# Apply foo to the data n times
for _ in range(n):
    data = client.map(foo, x, resources={'process': 1)

# Save the processed data
data.map(save, x, resources={'process': 1)

# Retrieve results
client.gather(data)

我希望图像可以在工作人员可用的空间中进行处理,但似乎图像都同时加载到不同的工作人员上。

编辑: 我的问题是所有任务都分配给工作人员,他们没有足够的内存。我发现了如何限制工作人员在单个时刻处理的任务数[此处为{https://distributed.readthedocs.io/en/latest/resources.html#resources-are-applied-separately-to-each-worker-process](see)。 但是,由于这个限制,当我执行任务时,它们都完成了读取步骤,然后是处理步骤,最后是保存步骤。这是一个问题,因为映像已溢出到磁盘上。

是否有一种方法可以使每个任务在开始新任务之前完成? 例如在Worker-1上:read(img1)-> process(img1)-> save(img1)-> read(img2)-> ...

1 个答案:

答案 0 :(得分:0)

Dask通常不知道任务需要多少内存,它只能知道输出的大小,并且只有完成后才知道。这是因为Dask只需执行pthon函数,然后等待它完成即可。但是所有事情都会在python函数中发生。通常,您应该期望在拥有可用的工作程序核心​​后就开始执行尽可能多的任务。

如果您想要较小的总内存负载,那么您的解决方案应该很简单:拥有足够少的工作程序,因此,如果所有工作程序都在使用您可以期望的最大内存,那么您仍然有一些空闲空间。系统来应对。

要编辑:您可能希望在提交之前尝试在图形上运行优化(尽管我认为这应该会发生),因为听起来您的线性任务链应该“融合”。 http://docs.dask.org/en/latest/optimize.html