Bag

Dask Bag 对通用 Python 对象的集合实现了诸如 map, filter, foldgroupby 等操作。它利用 Python 迭代器以并行方式完成此任务,且内存占用小。它类似于并行版本的 PyToolz 或 Python 风格的 PySpark RDD

示例

访问 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 工作流程都是易于并行化的,或者通过聚合减少了工作进程之间移动的数据量。

洗牌

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

这些洗牌操作开销很大,并且由诸如 dask.dataframe 等项目处理得更好。最佳做法是使用 dask.bag 清理和处理数据,然后将其转换为 Array 或 DataFrame,再进行需要洗牌步骤的更复杂操作。

已知限制

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

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

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

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

  4. Bag 的 groupby 速度较慢。如果可能,您应尽量使用 Bag 的 foldby。然而,使用 foldby 需要更多思考。

名称

Bag 是数学上指允许重复元素的无序集合。它是 多重集 (multiset) 的一个友好同义词。Bag 或多重集是集合概念的一种推广,与集合不同之处在于它允许包含多重集的多个元素实例

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

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

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

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