Dask 比 numpy 慢,只有一块



我是一个新的dask用户,我正在尝试在我的程序中运行函数点。我注意到 dask 的功能点比它的 numpy 版本慢,即使我在整个矩阵中只使用一个块。如何解释这种行为?

import dask.array as da 
import numpy as np
x = da.random.normal(10, 0.1, size=(20000 * 100000), chunks=(20000 * 100000))
z = x.dot(x)
%time z.compute()
'''
CPU times: user 1min 1s, sys: 17.3 s, total: 1min 18s
Wall time: 52 s
'''
y = x.compute()
%time w =y.dot(y)
'''
CPU times: user 19 s, sys: 8.24 s, total: 27.2 s
Wall time: 767 ms
'''

用完全不同的方法再次回答...你的性能测试对DASK真的很不公平。

测试中的很大一部分时间是通过分配一个 16GB 的数组并用正态分布的随机值填充它来占用的。测试的第一行,在其中定义数组x,仅计划此操作。然后,dask 必须在%timed 测试期间执行此分配和人口操作。在 numpy 测试中,您首先计算y,为 numpy 一个预定义的数组,并且您只是对点积进行计时。

Dask 是懒惰地评估的,这意味着它会在计算结果之前等待您需要结果。这真的很强大,因为这意味着你可以打开一个非常大的文件,对它做一堆数学运算,然后对结果进行子集,dask 只会读入并对所需的子集进行数学运算。另一方面,这确实意味着在解释错误和计时时必须非常小心,因为只有在使用阻塞调用(如compute)触发它时才会发生计算(其他示例是写入或绘图操作)。

建立一个公平的比较,两者更相似:

In [1]: import dask.array as da, numpy as np
In [2]: %%time
...: x = da.random.normal(10, 0.1, size=(20000 * 100000), chunks=(20000 * 100000))
...: z = x.dot(x)
...: z.compute()
...:
...:
CPU times: user 48.4 s, sys: 15.9 s, total: 1min 4s
Wall time: 52.8 s
Out[2]: 200020152771.42023
In [3]: %%time
...: x = np.random.normal(10, 0.1, size=(20000 * 100000))
...: z = x.dot(x)
...:
...:
CPU times: user 48.3 s, sys: 14.8 s, total: 1min 3s
Wall time: 53 s

另一方面,将 dask 数组作业拆分为 100 个块可以大大减少总时间:

In [4]: %%time
...: x = da.random.normal(10, 0.1, size=(20000 * 100000), chunks=(200 * 100000))
...: z = x.dot(x)
...: z.compute()
...:
...:
CPU times: user 54.4 s, sys: 1.61 s, total: 56 s
Wall time: 6.05 s
Out[4]: 200020035893.7987

如果你只使用一个块,那么 dask 不可能比 numpy 快。Dask 正在执行以下操作(非常简单):

  • 启动调度程序。这是一个单独的过程,其中包含一个数据库,用于跟踪和管理整个集群的工作
  • 启动工作线程。这是将进行计算的地方。工作线程连接到计划程序,计划程序指导群集上节点之间的通信
  • 计划作业。您的主线程与调度程序通信,将任务分解为可由 dask 理解和管理的部分,并执行理解数组亮度、类型和大小以及多阶段图中的依赖关系所需的任何计算。
  • 序列化、传输和反序列化输入数据。你已经很好地使用 dask.random 来创建数组,所以这里没有输入数据。但是你传递给 dask 的任何内容都需要转换为字节字符串,并通过端口在进程之间传递。
  • 在工作人员上执行任务。此步骤执行与 numpy 等效项完全相同的工作。由于它只是一个块,因此它不会并行发生。它只是发生在一个不同的过程中。
  • 序列化、传输和反序列化结果。答案需要通过端口发送回主线程。

这是一个简单的描述,但你明白了。你可以把 dask 运行时想象成(并行化 numpy 运行时)/n_workers + 非并行运行时 + 开销,开销不是微不足道的。在许多情况下,这是完全值得的开销 - 我每天都使用 dask 来处理太大的操作,无法用内存中的一台机器来处理。但它不仅神奇地让事情运行得更快 - 你需要明确考虑如何拆分工作以利用多个工人。

有关详细信息,请参阅有关最佳实践的 dask 文档。

最新更新