2016-07-29 4 views
3

私は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())がそれらのコピーをバイパスし、大量のプロセスごとのメモリオーバーヘッドを回避する可能性があります。私は二次補間が "プレインストップ"で行われているプレフィルタリングの興味深いオプションを提供しているのを見ていますが、これ以上はまだ検討していません(重要な問題はすべての共有データをプレフィルターしようとしています)。

+2

私の直感は、あなたが 'remotecall()'や '@ spawn'などを使う方が良いということです。私は、 '@ parallel'がデータの動きをどのように扱うかという点で、少し時間をとることができることを発見しました。したがって、Juliaの他の並列機能のうち、何が起こっているのかをより直接的に制御することができます。あなたや他の誰かがそれ以前にそれをうまくやっていないなら、今日または明日後で見てみることになるでしょう。 –

答えて

2

Apparently解決策は、補間のinterpolate!バージョンを使用することです。

using Interpolations 

# Function to compute via interpolator 
function test(volume) 

    image=SharedArray(Float32,(512,512)) 

    sampler=interpolate!(
    volume, 
    Interpolations.BSpline(Interpolations.Linear()), 
    Interpolations.OnGrid() 
) 

    @sync @parallel for i=1:512*512 
    x,y=ind2sub((512,512),i) 
    image[x,y]=sampler[x,y,512] 
    end 
    sdata(image) 
end 

# Initialize 1GByte of SharedArray 
volume=SharedArray(Float32,(512,512,1024)) # 1 GByte of shared data 
volume[:,:,:]=rand(Float32,(512,512,1024)) 

println(mean(test(volume))) 

も同様にあまりにも高次の補間方法を使用することが可能であり得るヒントが、線形補間が私の目的には十分であるprefilter!あります:私はそれで投げるように、これはできるだけ多くのワーカープロセスとの素晴らしい作品。

+0

スーパー、これに決着があることをとてもうれしく思います! –

関連する問題