Bag

Dask Bag 在通用 Python 对象集合上实现了 map, filter, foldgroupby 等操作。它使用 Python 迭代器并行执行这些操作,且内存占用小。它类似于 PyToolz 的并行版本,或 PySpark RDD 的 Pythonic 版本。

示例

访问 https://examples.dask.org.cn/bag.html 查看和运行使用 Dask Bag 的示例。

设计

Dask Bag 协调许多 Python 列表或迭代器,每个列表或迭代器构成更大集合的一个分区。

常见用途

Dask Bag 常用于并行化对非结构化或半结构化数据(如文本数据、日志文件、JSON 记录或用户定义 Python 对象)进行的简单计算。

执行

对 Bag 的执行提供两个好处:

  1. 并行:数据被分割,允许多个核心或机器并行执行

  2. 迭代:数据延迟处理,即使在单台机器上的单个分区内,也能平滑执行大于内存的数据

默认调度器

默认情况下,dask.bag 使用 dask.multiprocessing 进行计算。好处是 Dask 绕过了 GIL,并对纯 Python 对象使用多核。缺点是 Dask Bag 在包含大量工作进程间通信的计算中表现不佳。对于常见操作,这很少是一个问题,因为大多数 Dask Bag 工作流程都是高度并行的,或导致工作进程间数据移动很少的规约操作。

Shuffle

一些操作,例如 groupby,需要大量的工作进程间通信。在单台机器上,Dask 使用 partd 来执行高效、并行、溢出到磁盘的 shuffle 操作。在集群中工作时,Dask 使用基于任务的 shuffle。

这些 shuffle 操作开销较大,更适合由 dask.dataframe 等项目处理。最好使用 dask.bag 来清洗和处理数据,然后将其转换为 array 或 DataFrame,再进行需要 shuffle 步骤的更复杂操作。

已知限制

Bag 提供了非常通用的计算能力(任意 Python 函数)。这种通用性是有代价的。Bag 存在以下已知限制:

  1. 默认情况下,它们依赖于多进程调度器,该调度器本身有一系列已知限制(参见 共享内存

  2. Bag 是不可变的,因此您无法更改单个元素

  3. Bag 操作通常比 array/DataFrame 计算慢,就像标准 Python 容器通常比 NumPy 数组和 Pandas DataFrame 慢一样

  4. Bag 的 groupby 速度较慢。如果可能,您应该尝试使用 Bag 的 foldbyfoldby 的使用需要更多考虑。

名称

Bag 是数学中用于指代允许重复元素的无序集合的名称。它是 多重集 (multiset) 的一个友好同义词。Bag,或多重集,是集合概念的一种推广,与集合不同的是,它允许其元素有多个实例。

  • list: 有序允许重复 的集合,[1, 2, 3, 2]

  • set: 无序不允许重复 的集合,{1, 2, 3}

  • bag: 无序允许重复 的集合,{1, 2, 2, 3}

所以,bag 类似于 list,但它不保证元素间的顺序。可以有重复元素,但您不能要求第 i 个元素。