簡體   English   中英

Dask 比 numpy 慢一個塊

[英]Dask slower than numpy with one chunk

我是一個新的 dask 用戶,我正在嘗試在我的程序中運行 function 點。 我注意到即使我在整個矩陣中只使用一個塊,dask 的 function 點也比其 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 不可能比 numpy 快。 Dask 正在執行以下操作(非常簡單):

  • 啟動調度程序。 這是一個帶有數據庫的單獨進程,用於跟蹤和管理集群中的工作
  • 開始工人。 這是進行計算的地方。 工作人員連接到調度程序,調度程序指導集群上節點之間的通信
  • 安排工作。 您的主線程與調度程序通信以將任務分解為 dask 可以理解和管理的部分,並執行任何計算以了解數組尺寸、類型和大小,以及多階段圖中的依賴關系。
  • 序列化、傳輸和反序列化輸入數據。 您已經很好地使用 dask.random 創建數組,因此這里沒有輸入數據。 但是您傳遞給 dask 的任何內容都需要轉換為字節字符串並通過端口在進程之間傳遞。
  • 在工作人員上執行任務。 此步驟與您的 numpy 等效項完全相同。 由於它只是一個塊,它不會並行發生。 它只是發生在不同的過程中。
  • 序列化、傳輸和反序列化結果。 答案需要通過端口發送回主線程。

這是一個簡單的描述,但你明白了。 您可以將 dask 運行時視為(並行化 numpy 運行時)/n_workers + 非並行化運行時 + 開銷,而開銷並非微不足道。 在許多情況下,這完全值得開銷——我每天都使用 dask 來處理太大而無法用 memory 中的一台機器處理的操作。 但它不僅僅神奇地讓事情運行得更快——你需要明確地考慮如何拆分工作以利用多個工人。

有關更多信息,請參閱最佳實踐中的 dask 文檔。

用完全不同的方法再次回答......你的性能測試對dask真的很不公平。

分配一個 16GB 的數組並用正態分布的隨機值填充它會占用測試中的大部分時間。 測試的第一行,您定義數組x ,您只安排此操作。 然后,dask 必須在%time d 測試期間執行此分配和填充操作。 在 numpy 測試中,您首先計算y ,給 numpy 一個預定義的數組,並且您只是對點積進行計時。

Dask 是懶惰地評估的,這意味着它會在計算之前等待您需要結果。 這真的很強大,因為這意味着您可以打開一個非常大的文件,對其進行大量數學運算,然后對結果進行子集化,而 dask 只會讀入並在所需的子集上進行數學運算。 另一方面,這確實意味着您在解釋錯誤和計時時必須非常小心,因為計算僅在您使用諸如compute之類的阻塞調用觸發它時發生(其他示例是寫入或 plot 操作)。

建立一個公平的比較,兩者更相似:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM