大きな(ギガバイトスケール)引数を持つDaskを使用して関数を送信したいと思います。これを行うための最良の方法は何ですか?この関数をさまざまな(小さな)パラメーターで何度も実行したいと思います。
これはconcurrent.futuresインターフェースを使用します。 dask.delayedインターフェースも同じように簡単に使用できます。
x = np.random.random(size=100000000) # 800MB array
params = list(range(100)) # 100 small parameters
def f(x, param):
pass
from dask.distributed import Client
c = Client()
futures = [c.submit(f, x, param) for param in params]
しかし、これは私が予想するよりも遅いか、メモリエラーが発生します。
さて、ここで問題なのは、各タスクに大きな配列x
が含まれていることです。送信する100個のタスクごとに、x
をシリアル化し、スケジューラーに送信し、ワーカーに送信する必要があります。
代わりに、アレイをクラスターに1回送信します。
[future] = c.scatter([x])
これで、future
は、クラスター上に存在する配列x
を指すトークンになります。これで、ローカルクライアントのnumpy配列の代わりに、このリモートフューチャーを参照するタスクを送信できます。
# futures = [c.submit(f, x, param) for param in params] # sends x each time
futures = [c.submit(f, future, param) for param in params] # refers to remote x already on cluster
これにより、はるかに高速になり、Daskがデータの移動をより効果的に制御できるようになりました。
最終的に配列xをすべてのワーカーに移動する必要があると予想される場合は、配列をブロードキャストして開始することをお勧めします。
[future] = c.scatter([x], broadcast=True)
先物はdask.delayedでも問題なく機能します。ここにはパフォーマンス上の利点はありませんが、このインターフェイスを好む人もいます。
# futures = [c.submit(f, future, param) for param in params]
from dask import delayed
lazy_values = [delayed(f)(future, param) for param in params]
futures = c.compute(lazy_values)