16

RStudio を使用して、16 コアの CPU と 64 GB の RAM を搭載した Windows サーバーで foreach ループを実行しようとしています。(doParallel パッケージを使用)

「ワーカー」プロセスは、for ループの外側からすべての変数をコピーします (foreach ループの実行時に、Windows タスク マネージャーでこれらのプロセスのインスタンス化を監視することによって観察されます)。したがって、各プロセスで使用されるメモリが肥大化します。特に大きな変数のいくつかをグローバルとして宣言しようとしましたが、競合を避けるために、これらの変数が foreach ループ内から読み取られ、書き込まれないようにしました。ただし、プロセスは使用可能なすべてのメモリをすぐに使い果たします。

「ワーカー」プロセスが「読み取り専用」変数の一部のコピーを作成しないようにするメカニズムはありますか? そのような変数を宣言する特定の方法など?

4

1 に答える 1

21

パッケージは、ループdoParallelで参照されるワーカーに変数を自動エクスポートします。foreachそれをしたくない場合は、foreach「.noexport」オプションを使用して、特定の変数を自動エクスポートしないようにすることができます。しかし、私があなたを正しく理解していれば、あなたの問題は、R が後でこれらの変数の一部を複製していることです。これは、単一のマシン上の複数のプロセスで発生しているため、通常よりもさらに問題です。

R が変数の複製を作成しないように変数を宣言する方法はありません。コピーが作成されないように、問題のある変数をパッケージのようなオブジェクトに置き換えるかbigmemory、重複をトリガーしないようにコードを変更する必要があります。tracememオブジェクトが複製されるたびにメッセージが出力されるため、この関数を使用すると役立ちます。

ただし、ワーカーが必要とするデータを減らすことで、問題を回避できる場合があります。これにより、各ワーカーにコピーする必要があるデータの量が減り、メモリ フットプリントも減少します。

以下は、ワーカーに必要以上のデータを与える典型的な例です。

x <- matrix(1:100, 10)
foreach(i=1:10, .combine='c') %dopar% {
    mean(x[,i])
}

行列xforeachループ内で参照されるため、各ワーカーが列のサブセットのみを必要とする場合でも、各ワーカーに自動エクスポートされます。最も簡単な解決策は、列インデックスではなく、行列の実際の列を反復処理することです。

foreach(xc=x, .combine='c') %dopar% {
    mean(xc)
}

ワーカーに転送されるデータが少なくなるだけでなく、実際には各ワーカーがメモリ内に一度に 1 つの列を持つだけで済みます。これにより、大規模な行列のメモリ フットプリントが大幅に削減されます。ベクトルは依然として複製される可能性がありますxcが、 よりもはるかに小さいため、それほど害はありませんx

この手法は、 や などの「雪から派生した」関数を使用する場合にのみ役立ち、をdoParallel使用する場合には役立ちません。この手法を使用すると、使用時にループが少し遅くなる可能性があります。これは、すべてのワーカーが行列を無料で取得するためです。では、ワーカーが既に行列全体を持っているのに、なぜ列を移動するのでしょうか? ただし、Windows ではを使用できないため、この手法は非常に重要です。parLapplyclusterApplyLBmclapplymclapplyxdoParallelmclapply

重要なことは、ワーカーが作業を実行するために本当に必要なデータは何かを考え、可能であればそれを減らすようにすることです。iteratorsまたはパッケージの特別なイテレータを使用してそれを行うことができるitertools場合もありますが、アルゴリズムを変更することでそれを行うこともできます。

于 2013-08-05T13:27:19.887 に答える