41

言語をテストするために、Julia の動きの渦を計算してプロットする簡単なプログラムを採用しました。また、特別な理由もなく Python で記述しました。

(免責事項:1.私が読んだstackoverflowのすべてのパフォーマンス比較は、包括的/正確/適切に書かれていない/関連性がないなどの理由で非難されます.-これが実際の比較であるふりをしているわけではありません。 2. Python が最適化され、Cython などで実装される可能性があることは知っていますが、それはこの議論の一部ではなく、Julia と Python の同等の機能の参照用にここにあるだけです。)

コードとパフォーマンス結果はgist で確認できます。

Julia のパフォーマンスは、Fortran よりも大幅に遅くなります。計算自体の実行にかかる時間は次のとおりです (50000 タイム ステップ)。

Fortran: 0.051s
Julia: 2.256s
Python: 30.846s

Julia は Fortran よりもはるかに遅く (~44 倍遅い)、ギャップは狭まりますが、10 倍の時間ステップで依然として有意です( 0.50s vs 15.24s)。

これらの結果は、julia のホームページに表示されている結果とは大きく異なります。私は何を間違っていますか?Julia を修正して大幅に速くすることはできますか?

Julia Performance Tipsページと、Julia ホームページの比較の背後にあるコードをざっと読みましたが、修正すべき点は何もありません。

また興味深いことに、Julia は PyPlot の読み込みが非常に遅く ( 5secsish!!)、テキスト ファイルの読み取りは Python よりもはるかに遅いです。これらを改善するために何かできることはありますか?

上記の時間は、Julia と Python の読み込み時間を示していないことに注意してください。これは、AFAIK の計算にかかった生の時間です。コードを参照してください。fortran の場合はすべてです。いずれの場合も、速度を比較できるように、大まかにプロットをオフにしています。

コンピューター: Intel i7-3770、16GB RAM、SSD HD、OS: Ubuntu 13.10 64 ビット、Fortran: gfortran、GNU Fortran (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1、Julia: バージョン 0.3.0-prerelease+396 (2013-12-12 00:18 UTC)、コミット c5364db* (0 日古いマスター)、x86_64-linux-gnu、Python: 2.7.5+


アップデート:

Ivarne のアドバイスに基づいて、Julia スクリプトを書き直しました (上記の要旨で更新)。関数で単調な作業をカプセル化し、すべての型を宣言し、行列のさまざまな要素を必要に応じてさまざまな配列に分割します。(私は Float32 を試してみたので、かなりの数の場所に Float64 を含めましたが、ほとんどの場合はそうではありませんでした)。

結果は次のとおりです。

50,000時間ステップ:

Fortran: 0.051s (entire programme)
Julia: raw calc.: 0.201s, calc. and return (?): 0.758s, total exec.: 6.947s

500,000時間ステップ:

Fortran: 0.495s (entire programme)
Julia: raw calc.: 1.547s, calc. and return (?): 2.094s, total exec.: 8.521s

結論は:

  • ジュリアをかなりスピードアップできます。

  • Julia のパフォーマンスの測定方法によっては、Julia の見た目の速度に大きな影響を与える可能性があります。

4

2 に答える 2

32

私は Julia プロジェクトをしばらくフォローしており、コードに関連する可能性のあるコメントがいくつかあります。

  • グローバルスコープでかなりの量のコードを実行しているようです。すべての変数の型を反復ごとにチェックする必要があるため、Julia のグローバル環境は現在非常に低速です。通常、ループは関数内に記述する必要があります。
  • 配列スライスを使用しているようです。Juliaには高速な配列ビューがないため、現在はコピーを作成しています。サブアレイ用に切り替えようとするかもしれませんが、現在のところ、本来よりもはるかに遅いです。

PyPlot (およびその他のパッケージ) の読み込み時間は既知の問題であり、Julia コードを解析してマシン コードにコンパイルするには時間がかかるためです。このプロセスが瞬時に実行されるように、このプロセスのキャッシュを用意するというアイデアもありますが、まだ完成していません。Base ライブラリは現在、コンパイルされた状態でキャッシュされているため、ほとんどのインフラストラクチャは master ブランチにあります。

追加: 分離された関数でテストを実行しようとしたところ、これらの結果が得られました。この要点を参照してください

解析:

elapsed time: 0.334042578 seconds (11797548 bytes allocated)

そして、メインのテスト ループの連続するルーン文字をツリー化します。

elapsed time: 0.62999287 seconds (195210884 bytes allocated)
elapsed time: 0.39398753 seconds (184735016 bytes allocated)
elapsed time: 0.392036875 seconds (184735016 bytes allocated)

コンパイルされたコードが再度使用されたため、最初の実行後にタイミングがどのように改善されたかに注目してください。

更新 2 メモリ処理が改善された (割り当てはコピーされないため、配列の再利用を確保する) ことで、(私のマシンでは) タイミングが 0.2 秒に短縮されました。新しい配列の割り当てを避けるためにできることは確かに他にもありますが、そうすると少しトリッキーになり始めます。

この行はあなたが思うことをしません:

vx_old = vx

しかし、これはあなたが望むことをします:

copy!(vx_old, vx)

1 つのループをデベクトル化します。

x += 0.5*(vx + vx_old)*delta_t
y += 0.5*(vy + vy_old)*delta_t

に:

for i = 1:nvortex
    x[i] += 0.5*(vx[i] + vx_old[i])*delta_t
    y[i] += 0.5*(vy[i] + vy_old[i])*delta_t
end
于 2013-12-16T15:44:55.093 に答える
11

@ivarne がこれをカバーしていますが、もう少し注意が必要です。

julia> @time x=[1:10000];
elapsed time: 1.544e-5 seconds (80120 bytes allocated)

julia> @time y = x[1:10000];
elapsed time: 2.6857e-5 seconds (80120 bytes allocated)

わお。それは多くの時間とメモリです。

julia> @time z = sub(x,1:10000);
elapsed time: 6.239e-6 seconds (296 bytes allocated)

ずっといい。[:]することをしないのはなぜsubですか?知らない。まあ、私はそうします。インデックスに移動すると、Julia は次のように考えました。インデックスが 0 だけオフセットされているz[10]ことを除けば、z は x に似ています。ほらね。多くのインデックス作成を行う場合、そのわずかな追加が長期的にはコストがかかります。これを修正するには、ジュリアの宗教に反するポインターのような概念が必要です。z[10]x[10+0]

更新Julia が非推奨になり[:]ました (バージョン 0.4.0)

julia> @time x=[1:10000];
WARNING: [a] concatenation is deprecated; use collect(a) instead
in depwarn at deprecated.jl:73
in oldstyle_vcat_warning at ./abstractarray.jl:29
in vect at abstractarray.jl:32
while loading no file, in expression starting on line 155
0.530051 seconds (180.12 k allocations: 9.429 MB, 5.26% gc time)

julia> @time x=[1:10000];
WARNING: [a] concatenation is deprecated; use collect(a) instead
in depwarn at deprecated.jl:73
in oldstyle_vcat_warning at ./abstractarray.jl:29
in vect at abstractarray.jl:32
while loading no file, in expression starting on line 155
0.001373 seconds (303 allocations: 714.656 KB)

集めるほうが早い

julia> @ time x=collect(1:10000);
0.003991 seconds (35 allocations: 80.078 KB)

julia> @ time x=collect(1:10000);
0.000031 seconds (8 allocations: 78.406 KB)

サブアレイに相当

julia> @time z = sub(x,1:10000);
0.067002 seconds (36.27 k allocations: 1.792 MB)

julia> @time z = sub(x,1:10000);
0.000016 seconds (7 allocations: 288 bytes)
于 2013-12-16T23:21:46.160 に答える