私はJulia 0.4.6を現在64bit Debian Stretch( "testing")で使っています。私は現在、4コア4GバイトのVMで使用しています。各プロセスが独自のデータコピーを作成することなく、ワーカープロセスでSharedArrayでInterpolationsを使用するにはどうすればよいですか?
私が基本的にやっていることは、メインのプロセスに3D SharedArrayを設定してから、その3D配列から派生した2D配列の生産をワーカープロセスで並列化することです。キャッチは、補間を介して作業者がそのボリュームにアクセスするように(すべてのビットが実際に必要なビット数を予測できないため)、メモリの使用が急増しているように見えます。ここで
は...私は何をしようとしている証明するいくつかの最小限のコードです第1の補間無料版:正常に動作します
# Initialize 1GByte of SharedArray
volume=SharedArray(Float32,(512,512,1024)) # 1 GByte of shared data
volume[:,:,:]=rand(Float32,(512,512,1024))
# Function to compute directly from array
function test0()
image=SharedArray(Float32,(512,512))
@sync @parallel for y=1:512
for x=1:512
image[x,y]=volume[x,y,512]
end
end
sdata(image)
end
println(mean(test0()))
は私がいない労働者や-p 2でそれを実行するかどうか、-p 4、-p 8、-p 16(これはパフォーマンスの向上はあまりありませんが、これは単なる各反復で計算するもののモデルに過ぎません)。
しかし、このバージョン:
using Interpolations
# Function to compute via interpolator
function test1()
sampler=interpolate(volume,BSpline(Linear()),OnGrid())
image=SharedArray(Float32,(512,512))
@sync @parallel for i=1:512*512
x,y=ind2sub((512,512),i)
image[x,y]=sampler[x,y,512]
end
sdata(image)
end
println(mean(test1()))
は-p 2とスワップシステムを起動し、および-p 4はOutOfMemoryError
Sで終わる労働者を有しています。
私はがを推測していると、ワーカープロセスへの補間の直列化は、それが各ワーカーで非共有コピーへのデータの卸売をSharedArrayの上に座って、ただのコピーだという事実を見失うということです。
私の質問はこれを改善するために何ができるのですか?私がここでやろうとしていることに対してより良いパターンがありますか、@<something>
の狡猾な使い方は、各ワーカーが自分のコピーではなく共有配列を補間する結果になりますか?
更新:
このアプローチは有効に各ワーカープロセスに補間オブジェクトの作成をプッシュするようだ:
function test(volume)
image=SharedArray(Float32,(512,512))
sampler=Nullable()
@sync @parallel for i=1:512*512
x,y=ind2sub((512,512),i)
if isnull(sampler)
warn(STDERR,"Allocating sampler...")
sampler=Nullable(Interpolations.interpolate(sdata(volume),Interpolations.BSpline(Interpolations.Linear()),Interpolations.OnGrid()))
warn(STDERR,"...allocated sampler")
end
image[x,y]=get(sampler)[x,y,512]
end
sdata(image)
end
...しかし、それはまだ正確に同じ問題からとして苦しみますいくつかのワーカープロセスがスワップを開始したり、メモリが枯渇してサンプラの作成に失敗したりします。
Interpolations.jlコードを詳しく調べると、与えられた配列(明らかにコピーを取ることを意味する)をパッドしたりプレフィルターしたりすることが一般的に予想されます...しかし、私はまだJuliaをよく理解することができませんBSpline(Linear())
がそれらのコピーをバイパスし、大量のプロセスごとのメモリオーバーヘッドを回避する可能性があります。私は二次補間が "プレインストップ"で行われているプレフィルタリングの興味深いオプションを提供しているのを見ていますが、これ以上はまだ検討していません(重要な問題はすべての共有データをプレフィルターしようとしています)。
私の直感は、あなたが 'remotecall()'や '@ spawn'などを使う方が良いということです。私は、 '@ parallel'がデータの動きをどのように扱うかという点で、少し時間をとることができることを発見しました。したがって、Juliaの他の並列機能のうち、何が起こっているのかをより直接的に制御することができます。あなたや他の誰かがそれ以前にそれをうまくやっていないなら、今日または明日後で見てみることになるでしょう。 –