这项工作得到了 Continuum AnalyticsXDATA 项目以及 Moore Foundation 数据驱动发现计划的支持

为了增加透明度,我每周(大致上)会写一篇博客,介绍过去一周在 Dask 及相关项目上完成的工作。这篇日志涵盖了 2017-02-01 至 2017-02-20 期间的工作。这里的任何内容都尚未准备好用于生产环境。这篇博文是仓促写就的,因此请勿期待精雕细琢。

过去几周的主题

  1. 使用 Dask-GLM 进行性能分析实验
  2. 后续的图优化,包括非线性融合和避免重复创建新图
  3. Tensorflow 和 Keras 实验
  4. XGBoost 实验
  5. Dask 教程重构
  6. Google Cloud Storage 支持
  7. 清理 Dask + SKLearn 项目

Dask-GLM 和迭代算法

Dask-GLM 目前只是一堆求解器,例如 Newton(牛顿法)、Gradient Descent(梯度下降)、BFGS、Proximal Gradient Descent(近端梯度下降)和 ADMM。这些求解器可用于解决逻辑回归等问题,也可用于解决其他一些问题。这项工作的数学部分主要由 Capital One 的 Chris WhiteHussain Sultan 完成。

我们也一直在使用这个项目来探索 Dask 如何扩展机器学习算法。为此,我们在此处运行了一些基准测试:https://github.com/dask/dask-glm/issues/26 。这只是生成并解决了一些随机问题,但规模更大。

我们发现,有些算法(如 ADMM)表现非常出色,而对于其他算法(如梯度下降),调度器开销在扩展时可能成为一个严重的瓶颈。这主要是因为实际的内存中 NumPy 操作非常快;Dask 的任何迟缓都变得非常明显。以下是梯度下降的性能分析图:

注意所有的空白区域。这是 Dask 在不同迭代过程中思考要做什么的时间。我们现在正在努力减少这部分时间,以便使图表中所有有颜色的部分更紧密地挤在一起。这将带来整个项目的整体开销改进。

图优化 - 激进融合

我们正在通过两种方式来解决这个问题

  1. 更激进地将任务融合在一起,以便调度器需要考虑的块更少
  2. 在生成非常相似的图时避免重复工作

在第一种情况下,Dask 已经执行标准的任务融合。例如,如果你有以下两个任务

x = f(w)
y = g(x)
z = h(y)

Dask(以及自 20 世纪 80 年代以来所有其他类似编译器的项目)已经将其转换为以下形式

z = h(g(f(w)))

然而,许多这些数学或优化算法的棘手之处在于,它们大多是线性的,但并非完全如此。考虑以下示例:

y = exp(x) - 1/x

作为节点-链接图可视化时,这个图看起来像一个菱形,如下所示:

         o  exp(x) - 1/x
        / \
exp(x) o   o   1/x
        \ /
         o  x

像这样的图通常不会融合在一起,因为我们 可以 并行计算 exp(x)1/x。然而,当我们受到调度开销的限制并且有足够的并行工作要做时,我们宁愿将它们融合到一个任务中,即使我们失去了一些潜在的并行性。这里存在一个权衡,我们希望能够用一些并行性(我们有很多)来换取更少的开销。

相关的 PR 在此:dask/dask #1979,由 Erik Welch 提交(Erik 编写并维护了 Dask 的大部分图优化代码)。

图优化 - 结构共享

此外,我们不再在 dask.array 中复制图。每个集合,如 dask.array 或 dask.dataframe,都持有一个 Python 字典,其中包含构建该数组所需的所有任务。当我们在 dask.array 上执行操作时,会得到一个新的 dask.array,它带有一个指向新图的新字典。新图通常包含旧图的所有任务,外加一些新任务。因此,我们经常复制底层的任务图。

y = (x + 1)
assert set(y.dask).issuperset(x.dask)

通常这并不重要(复制图通常很廉价),但对于大型数组,当你进行许多数学运算时,这可能会变得非常昂贵。

现在我们将 Dask 图保存在一个自定义映射(类似字典的对象)中,该映射与其他数组共享子图。因此,我们很少进行不必要的复制,并且某些算法的开销大大降低。相关工作在 dask/dask #1985 中完成。

TensorFlow 和 Keras 实验

两周前,我与 Stan Seibert(Numba 开发者)进行了一次关于深度学习(Stan 的部分)和 Dask(我的部分)的讲座。作为讲座的一部分,我决定从 Dask 中启动 TensorFlow,并使用分布式 Dask 数组为 TensorFlow 提供数据。更多信息请参见 这篇博文

那个实验很好,因为它展示了从 Dask 部署和与其它分布式服务交互是多么容易。然而,从深度学习的角度来看,它还不成熟。幸运的是,它成功吸引了其他潜在开发者的注意(这是所有博文的真正目标),现在 Brett Naul 正在使用 Dask 来管理他使用 Keras 的 GPU 工作负载。Brett 贡献了代码,帮助 Dask 移动 Keras 模型。他似乎特别看重 Dask 的资源管理能力,这有助于他充分利用其工作站上的 GPU。

XGBoost 实验

在部署 TensorFlow 后,我们思考了如何对 XGBoost(另一个非常流行但差异很大的机器学习库)做同样的事情。相关的讨论在这里:dmlc/xgboost #2032,原型代码在这里:mrocklin/dask-xgboost。与 TensorFlow 一样,集成相对简单直接(如果说在这种情况下稍微更简单一些)。对我而言的挑战是,我对这些库设计用来解决的应用缺乏具体的经验。欢迎使用这些库进行生产的开源开发者提供反馈和协作。

Dask 教程重构

Github 上的 dask/dask-tutorial 项目最初是为 2015 年 7 月的 PyData Seattle 编写的(大约 19 个月前)。自那时以来,Dask 已经有了实质性的发展,但这是我们唯一的教学材料。幸运的是,Martin Durant 正在进行一项 相当认真的重写,既纠正了不再是现代 API 的部分,也增加了关于分布式计算和调试的新内容。

Google Cloud Storage

Dask 开发者(主要是 Martin)维护了一些库,帮助 Python 用户连接到分布式文件系统,如 HDFS(使用 hdfs3)、S3(使用 s3fs)和 Azure Data Lake(使用 adlfs),这些系统随后可以从 Dask 中使用。Martin 一直在开发 Google Cloud Storage 的支持(使用 gcsfs),同时还有一个使用相同 API 的小型项目。

清理 Dask + SKLearn 项目

去年,Jim Crist 发表了 三篇 很棒的 博文,介绍了如何将 Dask 与 SKLearn 一起使用。成果是一个名为 dask-learn 的小型库,它具有多种功能,有些功能非常有用,例如集群就绪的 Pipeline 和 GridSearchCV,而另一些则不那么有用。由于这项工作的实验性质,我们将该库标记为“尚未准备好使用”,这引起了一些潜在用户的好奇回复。

Jim 现在正忙于重整该项目,移除不太有用的部分,并将范围普遍缩小到严格意义上的模型并行算法。


博客评论由 Disqus 提供支持