使用dask下载,处理和连接到TFRecords的最佳方法

时间:2019-01-29 01:19:14

标签: python multiprocessing dask

我需要下载图像,对其进行一些图像处理,然后将其打包到n TFRecords中(例如,每个TFRecord 100张图像)。

使用python队列执行此操作,我将有d个下载线程,p个工作进程来处理图像,然后有w个工作进程将使用TFRecordWriter写入图像当它们可用时。

我想用dask尝试一下,所以我有类似的东西:

urls = bag.from_sequence(images_urls)
processed = urls.map(download_image).map(process)
by2 = processed.repartition(2).map_partitions(packing)
by3 = processed.repartition(3).map_partitions(packing)
bag.concat([by2, by3]).compute()

上述问题是map_partitions似乎无法以流方式获取图像。在分区上调用packing函数之前,整个分区似乎已在内存中。

上面的另一个烦人之处是,我在dask中看不到如何精确控制dag的哪一部分安排在哪里。下载程序可以与线程调度程序一起发生,其中线程处理和打包程序部分需要在不同的进程中发生。这是可能的还是您坚持在整个图形上使用某种调度程序?

1 个答案:

答案 0 :(得分:0)

如果您不希望bag批量加载多个图像,则可以将包构造为每个分区只有一个项目(因为您事先知道URL的数量)。实际上,在给定任务可以执行给定任务之前,确实需要将所有输入都存储在该工作器中。

也许更简单的方法是退回到使用delayed语法,例如

ims = [dask.delayed(download_image)(url) for url in images_urls]
processed = [dask.delayed(process)(im) for im in ims]
packs = [dask.delayed(packing)(processed[n:n+100]) for n in
         range(0, len(processed), 100)]
dask.compute(packs)

实际上,您只能有一个调度程序来执行图形,但是Dask会尝试调度程序任务在加载数据的位置运行。