Java矩阵数学库的性能?[关闭]


151

我们正在计算某种其运行时受矩阵运算约束的东西。(如果感兴趣,请在下面提供一些详细信息。)这种经历提示了以下问题:

人们对矩阵数学的Java库的性能(例如,乘法,逆运算等)是否有经验?例如:

我搜索后什么也没找到。


我们的速度比较细节:

我们正在使用Intel FORTRAN(ifort(IFORT)10.1 20070913)。我们已经使用Apache Commons Math 1.2矩阵操作在Java(1.6)中重新实现了它,并且它同意其所有准确性。(我们有使用Java的理由。)(Java加倍,Fortran real * 8)。Fortran:6分钟,Java 33分钟,同一台计算机。jvisualm性能分析显示在RealMatrixImpl。{getEntry,isValidCoordinate}上花费了很多时间(在未发布的Apache Commons Math 2.0中似乎消失了,但是2.0并没有更快)。Fortran使用Atlas BLAS例程(dpotrf等)。

显然,这可能取决于我们使用每种语言编写的代码,但是我们认为大部分时间都在等效的矩阵运算中。

在其他一些不涉及库的计算中,Java的运行速度并不慢,有时甚至快得多。


棘手的矩阵数学运算至少为O(n ^ 3)...情况越来越糟,我想您可以花时间测试...
Calyth

2
为什么需要逆运算?对于几乎所有应用程序,您都不需要实际的逆函数。由于稳定性问题,计算逆数是一个坏主意。
莺莺

1
@Calyth:是的,我们可以时间了。我想知道其他人是否已经拥有。@Ying Xiao:是的,要避免倒数。但是,使用此计算似乎最简单。参见en.wikipedia.org/wiki/…
dfrankow

2
@Calyth错了,使用分而治之的方法比O(n ^ 3)更有效的方法。
starblue 2009年

1
最快的本机性能来自JCublas。如果需要快速线性代数,则需要GPU。带有clMath的JOCL可能也可以工作,并且可以移植到CPU(甚至不需要重新编译的多平台)上,但是我尚未对其进行测试。
Aleksandr Dubinsky 2013年

Answers:


98

只是加上我的2美分。我已经比较了其中一些库。我试图将3000乘以3000的双精度矩阵与其自身相乘。结果如下。

将多线程ATLAS与C / C ++,Octave,Python和R配合使用,所需时间约为4秒。

结合使用Jama和Java,花费的时间为50秒。

将Colt和Parallel Colt与Java一起使用,花费的时间为150秒!

将JBLAS与Java结合使用时,由于JBLAS使用多线程ATLAS,因此再次花费了大约4秒钟的时间。

所以对我来说,很明显Java库的性能不是很好。但是,如果有人必须用Java编写代码,那么最好的选择是JBLAS。Jama,Colt和Parallel Colt速度不快。


3
我猜您使用的是多核计算机,因此这些结果是否受到库是否使用多核的影响?对于某些目的,例如,当使用mpi或hadoop等进行并行化时,重要的时间实际上是单时间,因为mpi / hadoop实现会并行处理事物。(至少,对我而言,jblas比jama快2.5,而不是jama快10倍。)
Hugh Perkins 2012年

17
我刚刚发布了netlib-java v1.0版...性能达到了同等水平(有时甚至超过)Fortran代码,并且它可以使用机器优化的本机,而无需更改用户代码。查找低级线性代数库时,请考虑这一点。我还维护了使用Netlib-java的MTJ。在Scala中,使用Breeze(也由供电netlib-java
fommil 2013年

4
使用ND4j和Java-我的旧笔记本电脑在219毫秒内完成了建议的乘法运算。尽管python + numpy在349
毫秒

2
为了补充我关于使用nd4j的最新评论,我使用了native-platform作为其后端,如果我使用cuda-platform则需要大约1毫秒
bennyl 2016年

您是否在某个地方发布了用于基准测试的代码?
bruziuz

108

我是Java Matrix Benchmark(JMatBench)的作者,在此讨论中我将提出自己的想法。

Java库之间存在显着差异,尽管在所有操作范围内都没有明确的赢家,但从最新的性能结果(2013年10月)可以看出,有几个明确的领导者。

如果您使用的是“大型”矩阵,并且可以使用本机库,那么显而易见的赢家(速度大约快3.5倍)是具有系统优化的netlib的MTJ。如果您需要纯Java解决方案,那么MTJOjAlgoEJMLParallel Colt是不错的选择。对于小型矩阵,EJML无疑是赢家。

我没有提到的库显示出严重的性能问题或缺少关键功能。


6
只是以为我会提到您的基准测试非常方便!感谢您抽出宝贵的时间。
hohonuuli 2012年

1
JBLAS似乎支持SVD作为'13九月的:mikiobraun.github.io/jblas/javadoc/org/jblas/...
Leopd

很棒的工作,很多。
webpat 2014年

您评估但未发布结果的库中是否有清单以及每个清单的原因?
凯文·克鲁姆维德

1
MTJ似乎被抛弃了:存储库已存档,最后一次提交是在2016
。– Danila Piatov

51

我是jblas的主要作者,并想指出我于2009年12月下旬发布了1.0版。我在包装上做了很多工作,这意味着您现在可以下载带有ATLAS和JNI库的“胖罐”适用于Windows,Linux,Mac OS X,32和64位(Windows除外)。这样,您只需将jar文件添加到类路径中即可获得本机性能。在http://jblas.org上查看!


2
受您工作的启发,我在netlib-java ;-)中做了类似的事情
fommil 2013年

2
哈哈,我也是杰根(
休·帕金斯

JogAmp的操作与此相同,请参见jogamp-fat.jar。好主意:)
gouessej

8

我不能对特定的库发表评论,但是原则上没有理由在Java中使此类操作变慢。Hotspot通常会执行您希望编译器执行的操作:将Java变量的基本数学运算编译为相应的机器指令(它使用SSE指令,但每个操作仅一个);如您所料,对数组元素的访问被编译为使用“原始” MOV指令;它决定何时可以分配变量到寄存器。它对指令进行重新排序以利用处理器体系结构。可能的例外是,正如我提到的,Hotspot将仅对每条SSE指令执行一项操作;原则上,您可以拥有一个经过优化的出色矩阵库,每个指令可以执行多个操作,尽管我不会 不知道您的特定FORTRAN库是否这样做,或者是否存在这样的库。如果确实如此,那么Java(或至少是Hotspot)目前就无法与之抗衡(尽管您当然可以编写自己的本机库,并从Java中调用这些优化方法)。

那么,这意味着什么?好:

  • 原则上,值得寻找性能更好的库,尽管不幸的是我不能推荐一个
  • 如果性能对您真的很关键,我会考虑只对自己的矩阵运算进行编码,因为这样一来,您就可以执行某些通常无法实现的优化,或者您所使用的某个特定的优化(如果您拥有多处理器机器,找出该库是否实际上是多线程的)

矩阵运算的障碍通常是数据局部性问题,当您需要逐行和逐列浏览时(例如在矩阵乘法中),就会出现数据局部性问题,因为您必须以优化一个或另一个的顺序存储数据。但是,如果您手写代码,有时可以合并操作以优化数据局部性(例如,如果将矩阵乘以其转换,则编写专用函数而不是合并,则可以将列遍历转换为行遍历两个库函数)。像往常一样,图书馆会为您带来非最佳性能,以换取更快的开发速度。您需要确定性能对您来说有多重要。


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矩阵。所有测试均在每次运行时在完全相同的矩阵上使用双精度进行(八度除外)。

免责声明-我不是线性代数的专家,也不隶属于上述任何库,这也不是严格的基准。这是一个“自制”测试,因为我有兴趣将JDK 1.7的性能提高到1.6以及将通用数学SVD的性能提高到jlapack。


8

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

  • 包装了Eigen C ++库http://eigen.tuxfamily.org,它是最快的免费C ++库之一
  • 相对简洁的语法,例如'mmul','sub'
  • 处理稠密和稀疏矩阵

通过将两个密集矩阵相乘来进行快速测试,即:

导入静态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花费的时间相同,但仅使用一个内核,因此Jeigen使用了总CPU的一半。Jeigen具有更简短的语法,即'mmul'与'multiplyRight'

Jeigen看起来很棒!我最近使用JNI和DLL在Java中实现了Eigen,用于解决非常大的稀疏矩阵。对于测试,我的DLL版本比并行colt快20倍(超过8000x8000矩阵)。我希望我知道Jeigen!
Z玻色子2015年

6

http://code.google.com/p/java-matrix-benchmark/上有Java可用的各种矩阵包的基准, 用于一些不同的硬件配置。但这并不能替代您自己的基准测试。

性能将随所拥有的硬件类型(cpu,内核,内存,L1-3缓存,总线速度),矩阵的大小和打算使用的算法而变化。不同的库对不同的算法在并发性上有不同的看法,因此没有一个答案。您可能还会发现,转换为本机库期望的形式所产生的开销抵消了您使用案例的性能优势(某些Java库在矩阵存储方面具有更灵活的选择,可用于进一步的性能优化)。

但是,一般而言,JAMA,Jampack和COLT越来越老,不能代表线性代数在Java中可用的当前性能状态。更现代的库更有效地利用了多个内核和cpu缓存。JAMA是参考实现,几乎实现了教科书算法,而很少考虑性能。COLT和IBM Ninja是最早显示Java性能的Java库,即使它们落后于本机库50%。


4

我是la4j(Java的线性代数)库的作者,这是我的观点。我从事la4j的研究已经3年了(最新版本是0.4.0 [2013年6月1日]),直到现在我才可以开始进行性能分析和优化,因为我已经介绍了所需的最小功能。因此,la4j并没有我想要的快,但是我花了很多时间来更改它。

我目前正在将新版本的la4j移植到JMatBench平台。我希望新版本将表现出比上一个版本更好的性能,因为我对la4j进行了一些改进,例如更快的内部矩阵格式,不安全的访问器和用于矩阵乘法的快速阻塞算法。


1
不-la4j确实没有竞争力。参见code.google.com/p/java-matrix-benchmark
Christopher Manning

它已经发生了很大的变化。自您回答以来,我已经发布了该库的两个版本。当前版本是0.4.0。它只是飞。
弗拉基米尔·科斯秋科夫(Fladimir Kostyukov)

3

Linalg代码在很大程度上依赖于Pentiums和更高版本的处理器的矢量计算功能(从MAP扩展开始,例如LAPACK,现在是Atlas BLAS),并非经过“惊人的优化”,而仅仅是行业标准。要在Java中复制性能,您将需要本机库。我遇到了与您描述的相同的性能问题(主要是为了能够计算Choleski分解),却发现没有什么真正有效的:Jama是纯Java,因为它应该只是实现者可以遵循的模板和参考套件。 ..从来没有发生过。您知道Apache的数学共通点...至于COLT,我仍然需要对其进行测试,但是它似乎严重依赖Ninja的改进,其中大多数是通过构建临时Java编译器来实现的,因此我怀疑它是否会有所帮助。那时,我认为我们“


好点子!一个带有Atlas的JNI包装器的alpha阶段项目:jblas.org。作者的博客文章:mikiobraun.blogspot.com/2008/10/…– dfrankow
2009年

3

我们已经使用COLT进行了一些相当大的认真财务计算,并且对此感到非常满意。在我们的概要分析代码中,我们几乎从未用自己的一种替换COLT实现。

在他们自己的测试中(显然不是独立的),我认为他们声称是Intel手动优化的汇编程序的两倍。正确使用它的诀窍是确保您了解他们的设计理念,并避免不必要的对象分配。


3

您是否看过英特尔数学内核库?它声称甚至胜过ATLAS。MKL可以通过JNI包装器在Java中使用


2
我们有。a)它的许可比Atlas更为严格(因此我们不能使用所有计算机);b)不是Java(正如我所说,我们有理由希望使用Java)。
dfrankow

即,这不是我有关Java库的问题的答案(但是我没有声誉来否决它)。
dfrankow

@dfrankow:我已经更新了答案,以解决您对在Java中使用它的担忧。
Zach Scrivena 09年

1
+1,如果您要寻找速度,这似乎是
可行

2
最后一个链接断开。
gouessej '17


2

您可能要签出jblas项目。这是一个相对较新的Java库,它使用BLAS,LAPACK和ATLAS进行高性能矩阵运算。

开发人员发布了一些基准测试,其中jblas相对于MTJ和Colt表现出色。


2

对于3d图形应用程序,lwjgl.util矢量实现的性能要比上述jblas高出约3倍。

我已经完成了vec4与4x4矩阵的一百万次矩阵乘法运算。

lwjgl大约需要18ms,jblas需要大约60ms。

(我认为,JNI方法不适用于相对较小的乘法的快速连续应用。因为转换/映射可能比乘法的实际执行花费更多时间。)


1

我发现,如果要创建很多高维矩阵,如果将其更改为使用一维数组而不是二维数组,则可以使Jama的速度提高约20%。这是因为Java不那么有效地支持多维数组。即。它创建一个数组数组。

Colt已经做到了这一点,但是我发现它比Jama更复杂,功能更强大,这也许可以解释为什么Colt使用简单函数的速度较慢。

答案确实取决于您在做什么。贾玛(Jama)不支持柯尔特(Colt)所做的事情中的一小部分,而这会使事情有所作为。




0

Matrix Tookits Java(MTJ)已经在前面提到过,但是对于任何涉足此线程的人来说,也许值得再次提及。对于那些感兴趣的人,似乎也有谈论要用MTJ替换apache commons math 2.0中的linalg库,尽管我不确定最近的进展如何。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.