2017-05-01 82 views
2

我試圖計算一個矩陣X的大小爲10,000 * 800,000的矩陣乘積Y = XX^T。矩陣X存儲在磁盤上的一個h5py文件中。生成的Y應該是存儲在同一個h5py文件中的10,000 * 10,000矩陣。這是一個可重現的示例代碼。dask核心外矩陣乘法調度

import dask.array as da 
from blaze import into 

into("h5py:///tmp/dummy::/X", da.ones((10**4, 8*10**5), chunks=(10**4,10**4))) 
x = into(da.Array, "h5py:///tmp/dummy::/X", chunks=(10**4,10**4))) 
y = x.dot(x.T) 
into("h5py:///tmp/dummy::/Y", y) 

我預計計算,以順利進行,因爲每個(10,000 * 10,000)塊應單獨換位,後面跟着一個點的產品,然後總結出最終結果。但是,運行此計算會填充我的RAM和交換內存,直到進程最終被終止。

這裏是計算圖的繪製樣品與dot_graph:Computation graph sample

按照SHEDULING文件,讓HTTP://dask.pydata.org/en/latest/scheduling-policy.html 我期望一旦個體計算出來,上面的tensordot中間結果被一個一個地總結爲最後的總和結果。這將釋放這些tensordot中間結果的記憶,以便我們不會面對記憶錯誤。

用較小的玩具如玩周圍:

from dask.diagnostics import Profiler, CacheProfiler, ResourceProfiler 

# Experiment on a (1,0000 * 5,000) matrix X split into 500 chunks of size (1,000 * 10) 
x = into(da.Array, "h5py:///tmp/dummy::/X", chunks=(10**3,10)))[:10**3,5000] 
y = x.T.dot(x) 
with Profiler() as prof, CacheProfiler() as cprof, ResourceProfiler() as rprof: 
    into("h5py:///tmp/dummy::/X", y) 
rprof.visualize() 

我得到以下顯示: Ressource profiler

凡綠條代表和操作,而黃色和紫色柱代表分別get_array和tensordot操作。這似乎表明總和操作在總結它們之前等待所有中間tensordot操作被執行。這也將解釋我的流程耗盡內存並被殺死。

所以我的問題是:

  • 是該和操作的正常行爲?
  • 有沒有辦法強制它計算所有中間產品tensordot產品計算並保存在內存中的中間和?
  • 如果沒有,是否有解決方案不涉及溢出到磁盤?

任何幫助非常感謝!

回答

0

一般來說,在小空間中執行密集矩陣乘法很難。這是因爲每個中間塊都會被幾個輸出塊使用。

按照SHEDULING文件,讓HTTP://dask.pydata.org/en/latest/scheduling-policy.html我希望上tensordot中間結果由一個概括一個到最後一筆只要他們已經被單獨計算,結果。

你已經顯示的圖有很多輸入到總和函數。在運行求和函數之前,Dask將等待所有這些輸入完成。任務調度程序不知道總和是關聯的並且可以一個一個地運行。缺乏語義信息是您使用像Dask這樣的通用任務調度系統而不是專門的線性代數庫所支付的代價。如果你的目標是儘可能有效地執行密集的線性代數,那麼你可能想看看其他地方;這是一個很好的領域。書面

所以你的內存需求至少8e5 * 1e4 * dtype.itemsize,假設在完全正確的順序DASK收益(它應該大多做)。

你可以嘗試以下操作:

  1. 沿非承包尺寸
  2. 使用版本DASK晚於0.14.1(0.14.2應該由5月5日發佈,2017年減少CHUNKSIZE ),我們在圖中明確地將這些大數據調用分解爲許多較小的調用。
  3. 使用分佈式調度程序,它可以更有效地處理將數據寫入磁盤。

    from dask.distributed import Client 
    client = Client(processes=False) # create a local cluster in this process 
    
+0

非常感謝@MRocklin! – Grin

+0

關於選項3,我遇到了https://github.com/dask/distributed/issues/927中提到的問題。 Hdf5序列化陣列似乎不適合分佈式調度器。修復它可以讓我使用分佈式調度程序的實時診斷/監視工具,這在這種情況下非常有用。另外,您是否知道pydata/python生態系統中的專門ooc線性代數庫?我最初開始使用dask是因爲它的核心線性代數特性與Numpy API結合在一起。 – Grin