サイズ10,000×800,000の行列Xについて、行列積Y = XX^Tを計算しようとしています。行列Xはディスク上のh5pyファイルに格納されます。結果として得られるYは、同じh5pyファイルに格納された10,000 * 10,000の行列でなければなりません。ここに再現可能なサンプルコードがあります。コア外マトリックスの行列乗算スケジューリングを一掃する
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でプロットである:私は期待//dask.pydata.org/en/latest/scheduling-policy.html ます:http shedulingドキュメントによるとComputation graph sample
上テンドルード中間結果は、個々に計算されるとすぐに最終的な結果に1つずつ合計される。これにより、これらテンポドット中間結果のメモリが解放されるため、メモリエラーに直面することはありません。小さなおもちゃの例で遊ん
:黄色と紫のバーがget_arrayとtensordotそれぞれ表している緑色のバーは、和演算を表し Ressource profiler
:
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()
私は次のような表示を得ますオペレーション。これは、和演算が、すべての中間テンソル演算が合計する前に実行されるのを待つことを示しているようです。これはまた私のプロセスがメモリ不足になって死に至ったことを説明します。
だから私の質問は以下のとおりです。
- は、和演算の正常な動作ですか?
- 中間のテンソル積が計算されてメモリに保存される前に、中間合計を計算する方法がありますか?
- そうでない場合は、ディスクへのこぼれには関係しない回避策がありますか?
大変助かりました!
どうもありがとう@MRocklin! – Grin
オプション3については、https://github.com/dask/distributed/issues/927に記載されている問題が発生します。 Hdf5シリアライズされた配列は、分散スケジューラーでうまく機能していないようです。それを修正すると、分散スケジューラのライブ診断/モニタリングツールを使用することができ、このような場合には非常に便利です。また、pydata/pythonエコシステムでは、特殊なooc線形代数ライブラリについて知っていますか?私はもともとdumpを使用し始めました。なぜなら、Numpy APIと組み合わされたコア線形代数機能がないからです。 – Grin