如何将Dask与自定义类一起使用

如何将Dask与自定义类一起使用,dask,Dask,我用Python扩展C++构建了一个分布式空间索引。我正在尝试使用Dask(第一次)而不是MPI。 当前的实现是可行的,但存在几个问题 与串行执行相比,关键部分是巨大的开销。我希望算法的速度几乎是线性的 Persist似乎没有达到我预期的效果,因为第一个查询的时间比第二个查询的时间长得多 在我看来,这个代码看起来很不规范,但正如我所说的,我对达斯克是新手。有更好的方法吗 当使用2d块时,我需要对延迟的对象进行索引。1d块不会出现这种情况,感觉很奇怪 该算法构建粒子排序列表,然后构建八叉树,其中节

我用Python扩展C++构建了一个分布式空间索引。我正在尝试使用Dask(第一次)而不是MPI。 当前的实现是可行的,但存在几个问题

  • 与串行执行相比,关键部分是巨大的开销。我希望算法的速度几乎是线性的

  • Persist似乎没有达到我预期的效果,因为第一个查询的时间比第二个查询的时间长得多

  • 在我看来,这个代码看起来很不规范,但正如我所说的,我对达斯克是新手。有更好的方法吗

  • 当使用2d块时,我需要对延迟的对象进行索引。1d块不会出现这种情况,感觉很奇怪

  • 该算法构建粒子排序列表,然后构建八叉树,其中节点通过一对(开始、结束)索引引用排序数组中的相邻粒子块。查询获取一个边界框并搜索八叉树中的重叠节点,从生成的候选对象中收集边界框中实际存在的粒子。构建和查询都是纯串行的

    并行化是通过随机分割粒子,在每个子集上建立树来完成的。查询将在所有子索引中广播,结果将重新连接在一起。达斯克在这里感觉很自然。我使用persist生成索引一次,并将其保留,因为我希望每个索引都有许多查询

    我尝试了
    map_块
    ,但这似乎只适用于数组到数组的转换。此外,还尝试了persist/compute的各种排列

    from dask.delayed import delayed
    from dask.distributed import LocalCluster, Client
    import dask.array as da
    
    # My custom octree index
    from pyoctree import Index
    
    # For reference, this runs on a 10 Core x 8 Thread cluster (POWER8)
    cluster = LocalCluster()
    client = Client()
    
    # Point count
    N = 100_000_000
    # Dimensionality
    D = 3
    # Chunk Count
    K = 10
    # Octree Levels
    L = 5
    
    # Delayed adapters for Dask
    @delayed
    def index(xs):
        """Create index"""
        return Index(L, xs)
    
    @delayed
    def query(index, ll, ur):
        """Bounding box query between lower left and upper right"""
        return index.query(*ll, *ur)
    
    # Random input: N random points in 3d
    array   = da.random.random((N, 3), chunks=(N//K,3)).astype(np.float32)
    # Split array
    splits  = array.to_delayed() 
    # Create index
    indices = [index(split[0]).persist() for split in splits]
    # This takes roughly 100ms
    
    # Execute a query
    queries = [query(index, (0.25, 0.25, 0.25), (0.35, 0.35, 0.35)) for index in indices]
    # Merge results
    parts   = [da.from_delayed(query, shape=(np.nan,3), dtype=np.float32) for query in queries]
    parts   = [part.compute_chunk_sizes() for part in parts]
    final   = da.concatenate(parts)
    result  = final.compute()
    # This takes 100s the first time and 800ms afterwards
    
    使用相同参数的串行执行需要240秒来构建索引,单个查询需要6毫秒。有了Dask,它是100秒的建筑,每次查询800毫秒。将粒子数N增加10倍,每个查询得到11秒,构建索引得到240秒。因此,达斯克似乎增加了N级的严重惩罚

    我很感激你给我的任何提示


    致以最诚挚的问候

    如果不进行分析,很难判断,但我的猜测是,您在每项任务中都包含了空间索引,因此会受到过度序列化的伤害

    我建议阅读本文件,了解如何确定成本:


    本文档旨在学习如何避免大型对象的序列化:

    如果不进行分析,很难判断,但我的猜测是,您在每个任务中都包含了空间索引,因此过度序列化会对您造成伤害

    我建议阅读本文件,了解如何确定成本:


    本文档旨在学习如何避免大型对象的序列化:

    谢谢,它解决了我在性能方面的问题。对于未来,我将如何使用Dask探查器诊断此问题?正如上面第一个链接中所述,您不会这样做。该文档对如何识别和分析序列化成本提出了建议。谢谢,这解决了我在性能方面的问题。对于未来,我将如何使用Dask探查器诊断此问题?正如上面第一个链接中所述,您不会这样做。该文档对如何识别和分析序列化成本提出了建议。