2016-07-24 14 views
7

中の残留ヒープ割り当てを離れて最適化私は、次のような出力が得られjulia --track-allocation prof.jlを実行しました:ジュリア

- using FixedSizeArrays 
    - 
    - immutable KernelVals{T} 
    -  wavenumber::T 
    -  vect::Vec{3,T} 
    -  dist::T 
    -  green::Complex{T} 
    -  gradgreen::Vec{3,Complex{T}} 
    - end 
    - 
    - function kernelvals(k, x, y) 
    -  r = x - y 
    0  R2 = r[1]*r[1] 
    0  R2 += r[2]*r[2] 
    0  R2 += r[3]*r[3] 
    0  R = sqrt(R2) 
    - 
    0  γ = im*k 
    0  expn = exp(-γ * R) 
    0  fctr = 1.0/(4.0*pi*R) 
    0  green = fctr * expn 
    64  gradgreen = -(γ + 1/R) * green/R * r 
    - 
    0  KernelVals(k, r, R, green, gradgreen) 
    - end 
    - 
    - function payload() 
    - x = Vec{3,Float64}(0.47046262275611883,0.8745228524771103,-0.049820876498487966) 
    0 y = Vec{3,Float64}(-0.08977259509004082,0.543199687600189,0.8291184043296924) 
    0 k = 1.0 
    0 kv = kernelvals(k,x,y) 
    - return kv 
    - end 
    - 
    - function driver() 
    - println("Flush result: ", payload()) 
    0 Profile.clear_malloc_data() 
    0 payload() 
    - end 
    - 
    - driver() 

私はgradgreen...を開始する行の最後のメモリ割り当てを取り除くことはできません。私は@code_warntype kernelsvals(...)を実行し、タイプの不安定性や不確実性がないことを明らかにしました。

割り当てパターンはjulia-0.4.6julia-0.5.0-preで同じです。

この関数は、私が実装している境界要素メソッドの内部カーネルになります。文字通り何百万回も呼び出され、物理メモリの倍数になるようなメモリ割り当てが行われます。

私はFixedSizeArraysを使用していた理由は、小さなArray秒の作成に関連する割り当てを避けるためです。

割り当てが報告される正確な場所は、コードに非常に敏感に依存します。ある時点では、メモリプロファイラーは、ラインを割り振る割り振りとして1/(4*pi*R)を非難していました。

予測可能な割り当てパターンをもたらすコードを書く方法に関するヘルプや一般的なヒントは高く評価されます。

答えて

3

いくつかの実験の後、私は最終的にすべての割り当てを取り除くことができました。原因は、FixedSizeArraysに拡張されたプロモーションアーキテクチャであることが判明しました。複雑なスカラーと実際のベクトルを乗算すると、途中で一時的に生成されるように見えます。

割り当てのない実行中

c = -(γ + 1/R) * green/R 
gradgreen = Vec(c*r[1], c*r[2], c*r[3]) 

結果とgradgreenの定義を交換します。私のベンチマークの例では、実行時間は6.5秒から4.15秒に短縮されました。合計割り当てサイズは4.5 GBから1.4 GBです。

EDT:この問題はFixedSizeArraysに報告されました。この問題を直ちに解決しました(ありがとうございました!)。割り当ては完全に消えた。

+0

これを把握し、個々のソリューションを開発し、それをグローバル化するために、うまくやってみよう! –