Python dask核外矩阵乘法调度
我试图计算一个10000*800000的矩阵X的矩阵积Y=XX^T。矩阵X以h5py文件的形式存储在磁盘上。结果Y应该是存储在同一h5py文件中的10000*10000矩阵。这是一个可复制的示例代码Python dask核外矩阵乘法调度,python,matrix-multiplication,h5py,dask,Python,Matrix Multiplication,H5py,Dask,我试图计算一个10000*800000的矩阵X的矩阵积Y=XX^T。矩阵X以h5py文件的形式存储在磁盘上。结果Y应该是存储在同一h5py文件中的10000*10000矩阵。这是一个可复制的示例代码 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, "h5p
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)
我希望这个计算能够顺利进行,因为每个(10000*10000)块都应该被单独转置,然后是一个点积,然后求和到最终结果。但是,运行此计算会填满我的RAM和交换内存,直到进程最终被终止
以下是使用点图绘制的计算图示例:
根据sheduling文件,http://dask.pydata.org/en/latest/scheduling-policy.html
我希望在单独计算后,将上张量的中间结果一个接一个地汇总到最后的汇总结果中。这将释放这些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()
我得到以下显示:
其中,绿色条表示求和运算,黄色和紫色条分别表示get_数组和tensordot运算。这似乎表明求和操作在求和之前会等待所有中间tensordot操作的执行。这也解释了我的进程内存不足并被杀死的原因
因此,我的问题是:
- 这是求和运算的正常行为吗
- 有没有办法强迫它先计算中间值 中间的tensordot乘积被计算并保存在内存中
- 如果没有,是否有不涉及溢出到磁盘的解决方法
非常感谢任何帮助 一般来说,在小空间中执行密集矩阵乘法是困难的。这是因为每个中间块将被多个输出块使用 根据sheduling文档http://dask.pydata.org/en/latest/scheduling-policy.html,我希望在单独计算后,将上张量的中间结果一个接一个地汇总到最后的汇总结果中 您所显示的图形有许多和函数的输入。Dask将等待所有这些输入完成后再运行sum函数。任务调度器不知道sum是关联的,可以逐段运行。语义信息的缺乏是使用Dask这样的通用任务调度系统而不是专用的线性代数库所付出的代价。如果你的目标是尽可能高效地执行密集线性代数,那么你可能想去别处看看;这是一块覆盖良好的田地 因此,如果Dask按照正确的顺序进行(通常应该这样做),那么您的内存需求至少是
8e5*1e4*dtype.itemsize
您可以尝试以下方法:
from dask.distributed import Client
client = Client(processes=False) # create a local cluster in this process
非常感谢@MRocklin!关于选项3,我遇到了中提到的问题。Hdf5序列化阵列似乎无法与分布式调度程序配合使用。对它进行修复将允许我使用分布式调度器的实时诊断/监视工具,这在这种情况下非常有用。另外,您知道pydata/python生态系统中有专门的ooc线性代数库吗?我最初开始使用dask是因为它的核心外线性代数特性与Numpy API相结合。