配置Dask Client并重组代码以并行化任务

时间:2020-09-22 16:37:40

标签: dask

我们有一个处理图像的代码,其中涉及运行MTCNNInception Resnet
由于我们有数百万个图像,因此我们希望将任务与Dask并行化。我们的问题是,尽管我们设法在图像的子集上运行代码-但在进行扩展(以在具有大量数据的Yarn Cluster上运行)时,代码崩溃了。
我们尝试以各种方式配置Client,但找不到正确的配置。
我们的图像存储在实木复合地板文件中(这就是我们收到它们的方式)。波纹管是在客户端上下文管理器中运行的代码:

def hex_to_img(hex_data: str) -> Image:
    try:
        bin_data = bytes.fromhex(hex_data)
        stream = io.BytesIO(bin_data)
        img = Image.open(stream).convert('RGB')
    except:
        img = np.NaN
    return img
    
    
def get_mtcnn_resnet() -> tuple:
    import os
    from facenet_pytorch import MTCNN, InceptionResnetV1
    os.environ['TORCH_HOME'] = '/opt/data/torch_home'  # Yes - this is a local path
    device = torch.device('coda:0' if torch.cuda.is_available() else 'cpu')
    mtcnn = MTCNN(
        image_size=160, margin=0, min_face_size=20, 
        thresholds=[0.6, 0.7, 0.7], factor=0.709, post_process=True,
        device=device
    )
    resnet = InceptionResnetV1(pretrained='vggface2').eval().to(device)
    return mtcnn, resnet


mtcnn, resnet = get_mtcnn_resnet()


def pipeline(path: str):
    df = dd.read_parquet(path, engine='pyarrow')
    df = dd.concat([df.get_partition(i) for i in range(5)])  # Without this line the code crashes
    df = df.assign(Image=df['ImageHex'].map(hex_to_img, meta=('Image', object))).drop('ImageHex', axis=1)
    df = df[~df['Image'].isna()]
    df = df.assign(MTCNN=df['Image'].map(mtcnn, meta=('MTCNN', object))).drop('Image', axis=1)
    df = df[~df['MTCNN'].isna()]
    df = df.assign(Embedding=df['MTCNN'].map(lambda x: resnet(torch.stack([x])).detach().numpy(), meta=('Embedding', object))).drop('MTCNN', axis=1)
    df = df[~df['Embedding'].isna()]
    print(df.compute().head())  

由于每个图像都是分别处理的,因此任务是并行的,并且图形非常简单。 在大型木地板文件上运行时,客户端崩溃(请参见dask crash performance_report)。该错误与调度程序和工作人员之间的通信有关,因此该报告似乎没有用。但是,当在镶木地板的一部分上运行并显示以下行时

df = dd.concat([i在范围(5)中的[df.get_partition(i)])

计算成功,但未使用所有可用资源(请参见dask successful performance_report)。从我们看到的结果来看,每个分区都有一个worker,其余所有分区都处于空闲状态。

我们也在LocalCluster上运行了代码,并且遇到了同样的问题。该代码只在小规模的数据上运行,但是对大量数据却失败(或花费很长的时间才能完成)(并且没有利用群集上的所有可用资源)。

使用compute(optimize_graph=False)运行并没有帮助。

  1. 是否有一种简单的方法可以使Dask与该任务并行化?
  2. 如果不是,是否需要管理DaskMaskRCNN repo中显示的所有工人模型的分配,还是有其他选择?我们知道mtcnnresnet对象必须可供每个工作人员使用,但无法理解为什么Dask无法处理scatter操作?
  3. dataframe中的图像提取为标准的alon文件格式以优化Dask的计算是否有益?从coiled youtube channel的示例来看,大多数处理过的图像都存储为单独的文件,我们想知道dask array是否更适合此类任务。

0 个答案:

没有答案