Javaマトリックス数学ライブラリのパフォーマンス?[閉まっている]


151

ランタイムが行列演算によって制限されているものを計算しています。(興味がある場合は、以下のいくつかの詳細。)この経験により、次の質問が生じました。

人々は、行列演算(たとえば、乗算、逆数など)のためのJavaライブラリのパフォーマンスの経験がありますか?例えば:

私は何も検索しませんでした。


速度比較の詳細:

Intel FORTRAN(ifort(IFORT)10.1 20070913)を使用しています。Apache commons math 1.2 matrix opsを使用してJava(1.6)で再実装し、そのすべての桁の精度に同意します。(Javaでそれを必要とする理由はあります。)(Javaダブルス、Fortranリアル* 8)。Fortran:6分、Java 33分、同じマシン。jvisualmプロファイリングは、RealMatrixImpl。{getEntry、isValidCoordinate}で費やされた多くの時間を示しています(これは、リリースされていないApache commons math 2.0ではなくなっているようですが、2.0はそれより速くありません)。FortranはAtlas BLASルーチン(dpotrfなど)を使用しています。

明らかに、これは各言語のコードに依存する可能性がありますが、ほとんどの場合、同等の行列演算にあると考えています。

ライブラリを含まない他のいくつかの計算では、Javaはそれほど遅くなく、場合によってははるかに高速です。


トリッキーな行列の数学演算は少なくともO(n ^ 3)です...悪くなれば
なるほど

2
なぜ逆行列が必要なのですか?ほとんどすべてのアプリケーションで、実際の逆は必要ありません。安定性の問題のため、逆の計算は悪い考えです。
Ying Xiao、

1
@Calyth:はい。他の人が既に持っていたかどうか私は思っていました。@英暁:はい、逆は避けてください。ただし、この計算を使用するのが最も簡単なようです。en.wikipedia.org/wiki/…を参照してください。
dfrankow 2009

2
@Calyth間違っています。分割統治法を使用するO(n ^ 3)よりも効率的な方法があります。
starblue

1
最速のネイティブパフォーマンスはJCublasによるものです。高速線形代数が必要な場合は、GPUが必要です。clMathを使用したJOCLも機能し、CPUに移植できます(再コンパイルなしのマルチプラットフォームでも可能です)が、テストはしていません。
Aleksandr Dubinsky

回答:


98

ちょうど私の2セントを追加します。これらのライブラリのいくつかを比較しました。私はそれ自体でdoubleの3000 x 3000行列を行列乗算しようとしました。結果は以下の通りです。

C / C ++、Octave、Python、RでマルチスレッドATLASを使用した場合、所要時間は約4秒でした。

JavaでJamaを使用した場合、所要時間は50秒でした。

JavaでColtとParallel Coltを使用した場合、所要時間は150秒でした。

JBLASをJavaで使用すると、JBLASがマルチスレッドATLASを使用するため、所要時間は再び約4秒でした。

だから私にとっては、Javaライブラリーのパフォーマンスがあまり良くなかったことが明らかでした。ただし、誰かがJavaでコーディングする必要がある場合、最良のオプションはJBLASです。Jama、Colt、Parallel Coltは高速ではありません。


3
マルチコアマシンを使用していたと思うので、これらの結果は、ライブラリがマルチコアを使用しているかどうかに強く影響されますか?mpi / hadoop実装が並列化を処理するため、一部の目的、たとえばmpiまたはhadoopなどを使用して並列化している場合、重要な時間は実際にはシングルコア時間です。(少なくとも、私にとって、jblasはjamaよりも約2.5倍高速でしたが、ジャマよりも10倍高速ではありませんでした。)
Hugh Perkins

17
私はnetlib-javaの v1.0をリリースしました...パフォーマンスはFortranコードと同等であり(時にはそれを超える)、ユーザーコードを変更せずにマシン最適化ネイティブを使用できます。低レベルの線形代数ライブラリを探すときは、これを考慮してください。私も維持します、netlib-javaを使用 MTJいます。Scalaでは、Breeze(これも搭載netlib-java)を使用してください
fommil

4
ND4jとJavaの使用-私の比較的古いラップトップは、推奨される乗算を219ミリ秒以内に完了します。python + numpyはそれを349ミリ秒以内に完了しますが
bennyl

2
そして、nd4jの使用に関する最後のコメントを追加するために、ネイティブプラットフォームをバックエンドとして使用しました。cuda-platformを使用する場合、約1ミリ秒かかります
bennyl

ベンチマーク用のコードをどこかに公開しましたか?
bruziuz

108

私はJava Matrix Benchmark(JMatBench)の作成者であり、この議論について私の考えを述べます。

Javaライブラリーの間には大きな違いがあり、操作の全範囲にわたって明確な勝者はありませんが、最新のパフォーマンス結果に見られるように、いくつかの明確なリーダーがいます(2013年10月)に。

「大きな」行列で作業していて、ネイティブライブラリを使用できる場合は、システム最適化されたnetlibを使用したMTJが勝者(約3.5倍高速)です。純粋なJavaソリューションが必要な場合は、MTJOjAlgoEJMLParallel Coltが適切な選択肢です。小さな行列の場合、EJMLが勝者です。

私が言及しなかったライブラリは、重大なパフォーマンスの問題を示したか、主要な機能がありませんでした。


6
あなたのベンチマークは本当に便利だと私が言ったと思いました!あなたの時間をそれに入れてくれてありがとう。
hohonuuli

1
JBLASは13
Leopd

素晴らしい仕事、たくさんあります。
webpat 2014年

評価したが結果を公開しなかったライブラリのどこかにリストと、それぞれの理由はありますか?
Kevin Krumwiede 16年

1
MTJは放棄されたようです。リポジトリはアーカイブされ、最後のコミットは2016
。– Danila Piatov 2018年

51

私はjblasのメイン著者であり、2009年12月下旬にバージョン1.0をリリースしたことを指摘したいと思います。パッケージングに多くの作業をしました。つまり、ATLASおよびJNIライブラリを使用して「ファットjar」をダウンロードできます。 Windows、Linux、Mac OS X、32および64ビット(Windowsを除く)。この方法では、jarファイルをクラスパスに追加するだけでネイティブのパフォーマンスが得られます。http://jblas.orgで確認してください。


2
あなたの仕事に触発されて、私はnetlib-javaで同様のことをしました;-)
fommil

2
ハハ、私もjeigenのために:-)
Hugh Perkins

JogAmpも同様です。jogamp-fat.jarを参照してください。良いアイデア:)
gouessej 2017

8

特定のライブラリについてコメントすることはできませんが、原則として、Javaでこのような操作が遅くなる理由はほとんどありません。Hotspotは通常、コンパイラーに期待する種類の処理を実行します。Java変数の基本的な数学演算を対応する機械語命令にコンパイルします(SSE命令を使用しますが、演算ごとに1つのみ)。配列の要素へのアクセスは、期待どおり「生の」MOV命令を使用するようにコンパイルされます。可能な場合、変数をレジスターに割り当てる方法を決定します。プロセッサアーキテクチャを利用するために命令を並べ替えます...可能な例外は、私が述べたように、HotspotはSSE命令ごとに1つの操作しか実行しないことです。原則的には、命令ごとに複数の操作を実行する、素晴らしく最適化されたマトリックスライブラリを使用できますが、特定のFORTRANライブラリがそうであるかどうか、またはそのようなライブラリが存在するかどうかを知る。存在する場合、現在Java(または少なくともHotspot)がそれと競合する方法はありません(もちろん、Javaから呼び出す最適化を使用して独自のネイティブライブラリを作成することもできます)。

では、これはどういう意味ですか?上手:

  • 原則として、パフォーマンスの高いライブラリを探し回る価値はありますが、残念ながら私は1つお勧めできません
  • パフォーマンスが非常に重要な場合は、独自の行列演算をコーディングすることを検討します。これは、ライブラリでは一般的にできない特定の最適化を実行できる場合や、使用していない特定のライブラリでは実行できない場合があるためです(マルチプロセッサマシン、ライブラリが実際にマルチスレッド化されているかどうかを確認します)

多くの場合、行列演算の妨げとなるのは、行列の乗算など、行と列の両方をトラバースする必要がある場合に発生するデータ局所性の問題です。これは、どちらか一方を最適化する順序でデータを格納する必要があるためです。しかし、コードを手書きする場合、データの局所性を最適化するために操作を組み合わせることができます(たとえば、マトリックスをその変換で乗算している場合、組み合わせの代わりに専用の関数を作成すると、列のトラバーサルを行のトラバーサルに変えることができます2つのライブラリ関数)。いつものように、ライブラリは開発を高速化する代わりに最適ではないパフォーマンスを提供します。あなたにとってパフォーマンスがどれほど重要であるかを決める必要があります。


8

Apache Commons Mathをjlapackと比較したところです。

テスト:ランダムな1024x1024行列の特異値分解。

マシン:Intel(R)Core(TM)2 Duo CPU E6750 @ 2.66GHz、linux x64

オクターブコード:A = rand(1024); tic; [U、S、V] = svd(A); toc

結果実行時間
-------------------------------------------------- -------
オクターブ36.34秒

JDK 1.7u2 64ビット
    jlapack dgesvd 37.78秒
    Apache Commons math SVD 42.24秒


JDK 1.6u30 64ビット
    jlapack dgesvd 48.68秒
    Apache Commons math SVD 50.59秒

ネイティブルーチン
Cから呼び出されたLapack *:37.64秒
インテルMKL 6.89秒(!)

私の結論は、JDK 1.7から呼び出されたjlapackは、lapackのネイティブバイナリパフォーマンスに非常に近いということです。Linuxディストリビューションに付属のlapackバイナリライブラリを使用し、dgesvdルーチンを呼び出して、U、S、VTマトリックスも取得しました。すべてのテストは、実行ごとにまったく同じ行列(Octaveを除く)で倍精度を使用して行われました。

免責事項-私は線形代数の専門家ではなく、上記のライブラリのいずれにも属していません。これは厳密なベンチマークではありません。JDK 1.7から1.6へのパフォーマンスの向上、およびCommons math SVDからjlapackへのパフォーマンスの比較に興味があったので、これは「自家製」のテストです。


8

Jeigen https://github.com/hughperkins/jeigen

  • Eigen C ++ライブラリhttp://eigen.tuxfamily.orgをラップしますこれは、利用可能な最速の無料C ++ライブラリの1つです。
  • 比較的簡潔な構文、たとえば「mmul」、「sub」
  • 密行列と疎行列の両方を処理します

2つの密行列を乗算することによる簡単なテスト、すなわち:

静的jeigen.MatrixUtil。*をインポートします。

int K = 100;
int N = 100000;
DenseMatrix A = rand(N, K);
DenseMatrix B = rand(K, N);
Timer timer = new Timer();
DenseMatrix C = B.mmul(A);
timer.printTimeCheckMilliseconds();

結果:

Jama: 4090 ms
Jblas: 1594 ms
Ojalgo: 2381 ms (using two threads)
Jeigen: 2514 ms
  • jamaと比較して、すべてが高速です:-P
  • jblasと比較すると、Jeigenはそれほど高速ではありませんが、スパース行列を処理します。
  • ojalgoと比較して、Jeigenは経過時間とほぼ同じですが、1つのコアしか使用しないため、JeigenはCPUの合計を半分使用します。Jeigenにはより簡潔な構文があります。つまり、「mmul」と「multiplyRight」です。

ジェイゲンはすごく見えます!私は最近、非常に大きなスパース行列を解決するために、JNIとDLLを使用してEigenをJavaに実装しました。DLLを使用した私のバージョンは、私のテスト用の並列コルトよりも20倍高速です(8000x8000マトリックスを超える)。ジェイゲンについて知っていたらよかったのに!
Zボソン

6

いくつかの異なるハードウェア構成用のhttp://code.google.com/p/java-matrix-benchmark/の Javaで利用可能なさまざまなマトリックスパッケージのベンチマークがあり ます。しかし、それはあなた自身のベンチマークを行うことに代わるものではありません。

パフォーマンスは、使用しているハードウェアの種類(CPU、コア、メモリ、L1-3キャッシュ、バス速度)、マトリックスのサイズ、および使用するアルゴリズムによって異なります。ライブラリが異なれば、アルゴリズムごとに同時実行性が異なるため、単一の答えはありません。また、ネイティブライブラリが期待する形式に変換するオーバーヘッドによって、ユースケースのパフォーマンスの利点が失われる場合があります(一部のJavaライブラリには、マトリックスストレージに関するより柔軟なオプションがあり、さらにパフォーマンスの最適化に使用できます)。

ただし、一般に、JAMA、Jampack、COLTは古くなっており、線形代数用のJavaで利用可能な現在のパフォーマンスの状態を表すものではありません。最新のライブラリでは、複数のコアとCPUキャッシュをより効果的に使用できます。JAMAはリファレンス実装であり、パフォーマンスをほとんど考慮せずに教科書アルゴリズムをほとんど実装しています。COLTとIBM Ninjaは、ネイティブライブラリに比べて50%遅れていたとしても、Javaでパフォーマンスが可能であることを示した最初のJavaライブラリでした。


4

私はla4j(Linear Algebra for Java)ライブラリの作者です。私は3年間la4jに取り組んでおり(最新リリースは0.4.0 [2013年6月1日])、必要な最小限の機能をカバーしたので、パフォーマンス分析と最適化を開始できるようになりました。そのため、la4jは思ったほど高速ではありませんが、変更に多くの時間を費やしています。

現在、la4jの新しいバージョンをJMatBenchプラットフォームに移植してます。私がla4jで行ったいくつかの改善(たとえば、高速な内部行列形式、安全でないアクセサー、行列乗算の高速ブロッキングアルゴリズム)があるため、新しいバージョンが以前のバージョンよりも良いパフォーマンスを示すことを願っています。


1
いいえ-la4jは本当に競争力がありません。code.google.com/p/java-matrix-benchmarkを
クリストファーマニング

それは大きく変わりました。あなたの回答以来、私はライブラリの2つのバージョンをリリースしました。現在のリリースは0.4.0です。そしてそれはただ飛ぶ。
Vladimir Kostyukov 2013

3

Pentiums以降のプロセッサのベクトルコンピューティング機能に大きく依存しているLinalgコード(LAPACKや現在のAtlas BLASなどのMMX拡張機能から開始)は、「ファンタスティックに最適化」されておらず、単に業界標準です。Javaでそのパフォーマンスを再現するには、ネイティブライブラリが必要になります。私はあなたが説明したのと同じパフォーマンスの問題を抱えており(主に、コレスキー分解を計算できるようにするため)、本当に効率的なものは何も見つかりませんでした:Jamaは純粋なJavaです。 ..決して起こらなかった。あなたはApacheの数学のコモンズを知っています... COLTについては、まだテストする必要がありますが、Ninjaの改善に大きく依存しているようです。そのほとんどは、アドホックJavaコンパイラを構築することによって達成されたため、役に立たないでしょう。その時点で、私たちは「


いい視点ね!AtlasのJNIラッパーを使用したアルファ段階プロジェクト:jblas.org。著者のブログ投稿:mikiobraun.blogspot.com/2008/10/…
dfrankow

3

私たちはいくつかのかなり大規模な深刻な財務計算にCOLTを使用しており、非常に満足しています。厳重にプロファイルされたコードでは、COLT実装を独自のものに置き換える必要はほとんどありませんでした。

彼ら自身のテスト(明らかに独立していない)では、インテルの手作業で最適化されたアセンブラールーチンの2倍以内であると主張しています。それをうまく使うコツは、あなたが彼らのデザイン哲学を理解し、無関係なオブジェクト割り当てを避けることを確実にすることです。


3

インテル・マス・カーネル・ライブラリーをご覧になりましたか?ATLASよりも優れていると主張しています。MKLは、JNIラッパーを介してJava使用できます。


2
それがあります。a)ライセンスはアトラスよりも制限的です(そのため、すべてのコンピューターを使用することはできません)。b)それはJavaではありません(私が言ったように、Javaになりたい理由があります)。
dfrankow 2009

つまり、これはJavaライブラリに関する私の質問への回答ではありません(しかし、私はそれを否定するという評判はありません)。
dfrankow 2009

@dfrankow:Javaでの使用に関する懸念に対処するために、回答を更新しました。
Zach Scrivena、2009

1
+1、あなたが探しているスピードなら、これが道のりのようだ
Gab Royer 2010年

2
最後のリンクは壊れています。
gouessej 2017


2

あなたはjblasをチェックアウトしたいかもしれませんプロジェクト。これは、BLAS、LAPACK、ATLASを使用して高性能のマトリックス演算を行う比較的新しいJavaライブラリです。

開発者は、jblasがMTJとColtに対して有利に機能しないいくつかのベンチマークを投稿しました。


2

3Dグラフィックスアプリケーションの場合、lwjgl.utilベクトルの実装は、上記のjblasの約3倍のパフォーマンスを発揮しました。

私はvec4と4x4マトリックスの100万のマトリックス乗算を実行しました。

lwjglは約18msで終了し、jblasは約60msを必要としました。

(私は、JNIアプローチは比較的小さな乗算の高速連続適用にはあまり適していないと思います。変換/マッピングは、実際の乗算の実行よりも時間がかかる場合があるためです。)


1

高次元の行列をたくさん作成している場合、2次元配列ではなく1次元配列を使用するように変更すると、Jamaを約20%高速化できることがわかりました。これは、Javaが多次元配列を効率的にサポートしていないためです。すなわち。配列の配列を作成します。

Coltは既にこれを実行していますが、Jamaよりも複雑で強力であることを発見しました。これは、Coltを使用すると単純な関数が遅くなる理由を説明している可能性があります。

答えは本当にあなたがやっていることに依存します。Jamaは、Coltができることの一部をサポートしていません。



0

無料で利用できるJava線形代数ライブラリは数多くあります。http://www.ujmp.org/java-matrix/benchmark/ 残念ながら、そのベンチマークは行列の乗算に関する情報しか提供しません(テストを転置すると、さまざまなライブラリがそれぞれの設計機能を利用できなくなります)。

注目すべきは、これらの線形代数ライブラリがさまざまな行列分解の計算を求められたときにどのように機能するかです。 http://ojalgo.org/matrix_compare.html


0

Matrix Tookits Java(MTJ)については既に言及しましたが、このスレッドに出くわした人にとっては、もう一度言及する価値があります。興味のある人にとっては、apache commons math 2.0の linalgライブラリをMTJに置き換えることについての話もあるようですが、それが最近どのように進んでいるかはわかりません。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.