我试图计算一个矩阵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产品计算并保存在内存中的中间和?
- 如果没有,是否有解决方案不涉及溢出到磁盘?
任何帮助非常感谢!
非常感谢@MRocklin! – Grin
关于选项3,我遇到了https://github.com/dask/distributed/issues/927中提到的问题。 Hdf5序列化阵列似乎不适合分布式调度器。修复它可以让我使用分布式调度程序的实时诊断/监视工具,这在这种情况下非常有用。另外,您是否知道pydata/python生态系统中的专门ooc线性代数库?我最初开始使用dask是因为它的核心线性代数特性与Numpy API结合在一起。 – Grin