web-dev-qa-db-ja.com

ジュリア言語は、それが主張するほど速いのですか?

次の この投稿 私はJuliaをGNU Octaveに対してベンチマークし、結果は julialang.org に示されている高速化と矛盾していました。

ジュリアとGNU Octave with CXXFLAGS='-std=c++11 -O3'、私が得た結果:

GNUオクターブ

a=0.9999;

tic;y=a.^(1:10000);toc
Elapsed time is 0.000159025 seconds.

tic;y=a.^(1:10000);toc
Elapsed time is 0.000162125 seconds.

tic;y=a.^(1:10000);toc
Elapsed time is 0.000159979 seconds.

-

tic;y=cumprod(ones(1,10000)*a);toc
Elapsed time is 0.000280142 seconds.

tic;y=cumprod(ones(1,10000)*a);toc
Elapsed time is 0.000280142 seconds.

tic;y=cumprod(ones(1,10000)*a);toc
Elapsed time is 0.000277996 seconds.

ジュリア

tic();y=a.^(1:10000);toc()
elapsed time: 0.003486508 seconds

tic();y=a.^(1:10000);toc()
elapsed time: 0.003909662 seconds

tic();y=a.^(1:10000);toc()
elapsed time: 0.003465313 seconds

-

tic();y=cumprod(ones(1,10000)*a);toc()
elapsed time: 0.001692931 seconds

tic();y=cumprod(ones(1,10000)*a);toc()
elapsed time: 0.001690245 seconds

tic();y=cumprod(ones(1,10000)*a);toc()
elapsed time: 0.001689241 seconds

ジュリアがGNUこれらの基本操作でオクターブよりも遅い理由を誰かが説明できますか?温めた後、オーバーヘッドなしでLAPACK/BLASを呼び出す必要がありますか?

編集:

コメントと回答で説明したように、上記のコードは優れたベンチマークではなく、実際のアプリケーションで言語を使用する利点を示していません。私は以前、ジュリアをより高速な「オクターブ/ MATLAB」と考えていましたが、それはそれ以上です。これは、生産的、高性能、科学計算への大きな一歩です。 Juliaを使用することにより、1)FortranおよびC++で書かれた研究分野でソフトウェアを凌perし、2)より優れたAPIをユーザーに提供できました。

40
juliohm

.^のようなベクトル化された操作は、実際には完全に特殊なCコードで実装されているため、Octaveが得意なものです。 Octaveのビルド時にコンパイルされるコードのどこかに、doubleおよびdoubleの配列の.^を計算するC関数があります。一方、ジュリアの.^演算子はジュリアで書かれています。

Julia> a = 0.9999;

Julia> @which a.^(1:10000)
.^(x::Number,r::Ranges{T}) at range.jl:327

その定義はこれで構成されます:

.^(x::Number, r::Ranges) = [ x^y for y=r ]

1次元配列内包表記を使用して、xyの範囲内の各値rに上げ、結果をベクトルとして返します。

エドワード・ガーソンは、ジュリアで最適なパフォーマンスを得るためにグローバルを使用するべきではないことはまったく正しいです。その理由は、実行が現在のスコープを離れる任意の時点で変更される可能性があるため、コンパイラはグローバルのタイプについて非常によく推論できないからです。現在のスコープを離れることはそれほど頻繁に起こるようには聞こえませんが、ジュリアでは、配列へのインデックス付けや2つの整数の追加などの基本的なことでさえ、実際にはメソッド呼び出しであり、したがって現在のスコープを離れます。ただし、この質問のコードでは、.^関数内ですべての時間が費やされるため、aがグローバルであるという事実は実際には重要ではありません。

Julia> @elapsed a.^(1:10000)
0.000809698

Julia> let a = 0.9999;
         @elapsed a.^(1:10000)
       end
0.000804208

最終的に、浮動小数点配列でベクトル化された操作を呼び出すだけであれば、Octaveは問題ありません。ただし、これは実際には、高レベルの動的言語でもほとんどの時間が費やされる場所ではありません。 forループを使用して配列を反復処理し、各要素をスカラー演算で処理したい場合は、Octaveがそのようなことで非常に遅いことがわかります。CまたはJuliaコードの何千倍も遅い同じこと。一方、Juliaでループを記述するのは完全に合理的なことです。実際、ソートコードはすべてJuliaで記述されており、パフォーマンスはCに匹敵します。また、パフォーマンスに関係のないJuliaを使用する他の多くの理由があります。 Matlabクローンとして、OctaveはMatlabの設計上の問題の多くを継承しており、汎用プログラミング言語としてはあまりうまくいきません。たとえば、OctaveやMatlabでWebサービスを記述したくはありませんが、Juliaでは quite easy です。

62
StefanKarpinski

あなたはジュリアのパフォーマンスの落とし穴であるグローバル変数を使用しています。

問題は、コードが別の関数を呼び出すたびにグローバルが潜在的に型を変更できることです。その結果、コンパイラーは、使用されるグローバル変数のタイプについて推測できない非常に遅いコードを生成する必要があります。

https://docs.julialang.org/en/stable/manual/performance-tips/ に沿ったコードの簡単な変更により、より満足のいく結果が得られるはずです。

14
EdwardGarson