153

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

行列演算 (乗算、逆数など) 用の Java ライブラリのパフォーマンスに関する経験はありますか? 例えば:

検索しても何も見つかりませんでした。


速度比較の詳細:

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

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

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

4

19 に答える 19

113

私はJavaMatrixBenchmark(JMatBench)の作成者であり、この議論について考えます。

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

「大きな」マトリックスを使用していて、ネイティブライブラリを使用できる場合、明確な勝者(約3.5倍高速)は、システムに最適化されたnetlibを備えたMTJです。純粋なJavaソリューションが必要な場合は、MTJOjAlgoEJMLParallelColtが適しています。小さな行列の場合、EJMLが明らかに勝者です。

私が言及しなかったライブラリは、重大なパフォーマンスの問題を示したか、主要な機能が欠落していました。

于 2011-12-09T04:13:09.620 に答える
101

私の2セントを追加するだけです。これらのライブラリのいくつかを比較しました。double の 3000 × 3000 行列をそれ自体で行列乗算しようとしました。結果は次のとおりです。

C/C++、Octave、Python、および R でマルチスレッド ATLAS を使用すると、所要時間は約 4 秒でした。

Java で Jama を使用すると、かかった時間は 50 秒でした。

Colt と Parallel Colt with Java を使用すると、かかった時間は 150 秒でした。

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

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

于 2010-06-17T20:11:20.960 に答える
53

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

于 2010-01-31T22:10:30.647 に答える
9

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 数学 SVD 42.24 秒


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

ネイティブ ルーチン
Lapack* C から起動: 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 の比較に興味があったため、これは「自作」のテストです。

于 2012-02-05T07:48:01.413 に答える
8

ジェイゲンhttps://github.com/hughperkins/jeigen

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

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

import static 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' です。
于 2012-10-04T06:28:25.640 に答える
8

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

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

  • 原則として、よりパフォーマンスの高いライブラリを探し回る価値はありますが、残念ながら私はお勧めできません
  • パフォーマンスが本当に重要な場合は、独自の行列演算をコーディングすることを検討します。これにより、ライブラリでは通常実行できない、または使用している特定のライブラリでは実行できない特定の最適化を実行できる可能性があるためです (ライブラリが実際にマルチスレッド化されているかどうかを調べる)

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

于 2009-02-09T20:45:21.437 に答える
6

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

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

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

于 2010-10-03T06:18:22.860 に答える
5

私はla4j(Java用線形代数)ライブラリの作者であり、ここに私のポイントがあります。私はla4jに3年間取り組んできました(最新リリースは0.4.0 [2013年6月1日])。最低限必要な機能について説明したので、パフォーマンスの分析と最適化を開始できるのは今だけです。そのため、la4jは思ったほど高速ではありませんが、変更するために多くの時間を費やしています。

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

于 2011-10-04T05:51:37.183 に答える
4

Intel Math Kernel Libraryをご覧になりましたか? ATLASよりも優れていると主張しています。MKL は、JNI ラッパーを介して Java で使用できます。

于 2009-02-09T19:45:21.923 に答える
3

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

于 2009-02-09T21:04:04.623 に答える
3

Pentium 固有のネイティブ コードの方がうまくいくという Varkhan の投稿に基づいています。

于 2009-02-09T22:38:22.197 に答える
3

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

彼ら自身のテスト (明らかに独立していない) では、インテルの手で最適化されたアセンブラー ルーチンの 2 倍以内であると主張していると思います。それをうまく使う秘訣は、彼らの設計哲学を理解し、余分なオブジェクトの割り当てを避けることです。

于 2009-02-12T15:55:31.990 に答える
2

3D グラフィックス アプリケーションの場合、lwjgl.util ベクトルの実装は、前述の jblas よりも約 3 倍優れています。

vec4 と 4x4 行列の行列乗算を 100 万回実行しました。

lwjgl は約 18 ミリ秒で完了し、jblas は約 60 ミリ秒かかりました。

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

于 2012-02-24T02:43:59.983 に答える
2

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

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

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

于 2009-05-18T18:49:31.400 に答える
2

jblasプロジェクトを確認してみてください。これは、BLAS、LAPACK、ATLAS を使用して高パフォーマンスの行列演算を行う比較的新しい Java ライブラリです。

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

于 2009-07-20T05:32:28.797 に答える
1

UJMPもあります

于 2009-07-20T05:48:39.437 に答える
0

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

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

于 2009-05-18T12:11:46.477 に答える
0

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

于 2009-07-08T15:30:38.567 に答える
0

買い物リストに Apache Mahout を追加する必要があります。

于 2010-04-24T22:43:37.487 に答える