从分块到并行:Dask使Pandas运行更快

当内存无法容纳数据时,可以使用数据分块的方法:以数据块的形式分批加载到内存进行处理。这样就可以通过加载数据集的子集,来逐步处理整个数据集。

但是,虽然分块可以节省内存,但它并不能解决处理海量数据的另一个问题:计算力。

怎样才能加快数据的处理速度呢?

一种方法是利用多个CPU:现在,几乎每台电脑都有一个以上的CPU。如果是2个cpu,那么通常可以(几乎)以2倍的速度运行代码;若是4个cpu,那么将获得4倍的加速,以此类推。


另一种方法是利用数据分块技术。它不但有助于减少内存的使用量,还可以支持并行。让我们先了解一下其原理,然后在学习dask库是如何实现并行的。


快速的回顾一下:数据分块


在上一篇中,我们讨论了怎样通过按数据块来加载数据集以减少内存开销的方法,并演示了如何使用MapReduce 模式来构造代码。

在这个例子中,我们尝试计算出每个政党在每一条街道上的选民数量:

从分块到并行:Dask使Pandas运行更快

以数据块处理数据的一个关键要求是:相关函数可以独立运行。在上面的这个例子中,我们可以独立的计算出某个数据块中选民的数量,而不需要依赖于其它任何数据块。

如果可以独立的处理这些数据块,那么就意味着我们可以并行的处理多个数据块。利用电脑的多个CPU,加快运算速度!稍加思考就会发现,减少相加运算的步骤,依然能保持运算的独立性,当然就可以并行化运行:

A+B+C+D=(A+B)+(C+D)

那么如何以最少的工作量实现并行呢?


Dask:一个并行处理库

以可伸缩的方式做到并行的最简单方法之一是使用Dask库,这是一种适用于Python的灵活并行计算库。

在许多其他功能中,Dask提供了一个模拟Pandas的API,<同时透明地实现了分块和并行化


由于所有有难度的工作都由Dask来完成,所以我们可以更轻松的开始工作。具体来说,我们将不使用数据分块,而是切换到Pandas代码,该代码可将所有数据整体加载到内存中:

从分块到并行:Dask使Pandas运行更快

这当然不是理想的:它仅使用一个CPU,并且我们需要一次将所有数据加载到内存中。峰值内存使用情况如下所示:


从分块到并行:Dask使Pandas运行更快


使用Dask库模仿pandas的工作方式


Dask的工作方式包括两个步骤:

  • 首先,设置一个计算任务,内部表示为操作图。
  • 然后,在该图上进行实际的计算。

当Dask模拟Pandas API时,它实际上并没有计算任何东西。相反,它会记住您将要执行的第一步操作。仅在运行compute()命令之后,实际工作才会发生。

看起来很相似的代码,但是幕后却实现了数据分块和并行化。

这是我们如何使用Dask进行此计算:

从分块到并行:Dask使Pandas运行更快

请注意,大多数代码未更改!但是,正如我们将看到的,执行时间更快,内存使用也更低:


从分块到并行:Dask使Pandas运行更快


Dask(通常)使工作变得更轻松


简单的读取所有数据的panda代码和Dask代码非常相似。那么,怎样比较它们在内存使用上和在runtime上,以及在不采用多线程的情况下使用数据块的方式加载数据上的差别呢?

从分块到并行:Dask使Pandas运行更快


(如果您不知道wallclock和CPU时间之间的区别,请参阅本文了解详细信息)。


一般来说,简单版本在内存使用和CPU时间方面做得最差。CPU时间可能会稍差一些,因为它使用的算法无法在非常大的数据块上很好地工作:分块和Dask库都是在更小的数据块上工作。

分块的版本占用的内存最少,但是wallclock时间也好不到哪里去。

Dask库使用的内存比简单版本少得多,并且完成得最快(假设您有多个CPU)。


当然,Dask库并不是万灵药:

并行性有开销,它不会总是让事情完成得更快。而且它不会减少CPU时间,所以如果cpu负载已经饱和,它将不会提高wallclock时间。

需要进行一些调优。

更大的数据块增加了内存的使用量,但是在一定程度上也增加了处理速度。

如果待处理任务足够简单或快速,单线程的pandas可能更快。


对于处理海量数据的缓慢任务,绝对应该尝试Dask库。正如您所看到的,它只需要对现有的panda代码进行非常小的更改,就可以以更低的内存开销获得更快的运行速度。


英文原文:
https://pythonspeed.com/articles/faster-pandas-dask/
译者:sky


分享到:


相關文章: