dfr*_*kow 147 java math performance matrix
我们正在计算运行时受矩阵运算约束的东西.(如果感兴趣,请参阅下面的一些细节.)这次经历提出了以下问题
民间有没有使用Java库的矩阵数学性能经验(例如,乘法,逆等)?例如:
我搜查了一下,一无所获.
我们的速度比较详情:
我们使用的是英特尔FORTRAN(ifort(IFORT)10.1 20070913).我们使用Apache commons math 1.2矩阵运算在Java(1.6)中重新实现了它,并且它同意所有的精度数字.(我们有理由在Java中想要它.)(Java双打,Fortran真*8).Fortran:6分钟,Java 33分钟,同样的机器.jvisualm profiling显示了在RealMatrixImpl中花费了大量时间.{getEntry,isValidCoordinate}(在未发布的Apache commons math 2.0中似乎已经消失了,但2.0并不快).Fortran正在使用Atlas BLAS例程(dpotrf等).
显然这可能取决于我们在每种语言中的代码,但我们相信大部分时间都在等效的矩阵运算中.
在其他几个不涉及库的计算中,Java并没有慢得多,有时甚至更快.
les*_*mal 108
我是Java Matrix Benchmark(JMatBench)的作者,我将对这个讨论给出我的看法.
Java库之间存在显着差异,虽然在整个运营范围内没有明显的赢家,但在最新的绩效结果(2013年10月)中可以看到一些明显的领导者.
如果您正在使用"大型"矩阵并且可以使用本机库,那么明确的赢家(大约快3.5倍)是具有系统优化的netlib的MTJ.如果您需要纯Java解决方案,那么MTJ,OjAlgo,EJML和Parallel Colt都是不错的选择.对于小型矩阵,EJML是明显的赢家.
我没有提到的库显示出重大的性能问题或缺少关键功能.
小智 97
只是加我2美分.我比较了其中一些库.我试图矩阵乘以3000乘3000矩阵的双精度.结果如下.
使用带有C/C++,Octave,Python和R的多线程ATLAS,所花费的时间大约为4秒.
使用Jama with Java,所用时间为50秒.
使用Colt和Parallel Colt与Java一起使用时间为150秒!
使用JBLAS和Java,由于JBLAS使用多线程ATLAS,所以花费的时间大约为4秒.
所以对我来说很明显,Java库的表现并不好.但是,如果有人必须用Java编写代码,那么最好的选择是JBLAS.贾马,科尔特和平行柯尔特并不快.
小智 50
我是jblas的主要作者,并想指出我在2009年12月底发布了1.0版.我在包装上做了很多工作,这意味着你现在可以下载一个带有ATLAS和JNI库的"胖罐子"适用于Windows,Linux,Mac OS X,32位和64位(Windows除外).这样,只需将jar文件添加到类路径中,即可获得本机性能.请访问http://jblas.org查看!
我不能真正评论特定的库,但原则上这些操作在Java中没有什么理由变慢.Hotspot通常会执行您希望编译器执行的操作:它将Java变量的基本数学运算编译为相应的机器指令(它使用SSE指令,但每个操作只有一个); 对数组元素的访问被编译为使用"原始"MOV指令,如您所期望的那样; 它可以决定如何在变量寄存器中分配变量; 它重新命令指令以利用处理器架构......可能的例外是,正如我所提到的,Hotspot每个SSE指令只执行一次操作; 原则上你可以有一个奇妙优化的矩阵库,每个指令执行多个操作,虽然我不 或者知道,例如,您的特定FORTRAN库是否这样做,或者是否存在这样的库.如果确实如此,那么Java(或者至少是Hotspot)目前无法与之竞争(尽管您当然可以编写自己的本机库以及从Java调用的优化).
那么,这意味着什么?好:
矩阵操作的障碍通常是当您需要逐行和逐列遍历时出现的数据局部性问题,例如在矩阵乘法中,因为您必须以优化其中一个的顺序存储数据.但是如果你手写代码,你有时可以结合操作来优化数据局部性(例如,如果你将矩阵乘以它的变换,如果你编写一个专用函数而不是组合,你可以将列遍历转换为行遍历两个库函数).像往常一样,图书馆会给你非最佳表现以换取更快的发展; 你需要决定性能对你有多重要.
我只是将Apache Commons Math与jlapack进行了比较.
测试:随机1024x1024矩阵的奇异值分解.
机器:Intel(R)Core(TM)2 Duo CPU E6750 @ 2.66GHz,linux x64
八度代码:A = rand(1024); 抽动; [U,S,V] = SVD(A); TOC
results execution time
---------------------------------------------------------
Octave 36.34 sec
JDK 1.7u2 64bit
jlapack dgesvd 37.78 sec
apache commons math SVD 42.24 sec
JDK 1.6u30 64bit
jlapack dgesvd 48.68 sec
apache commons math SVD 50.59 sec
Native routines
Lapack* invoked from C: 37.64 sec
Intel MKL 6.89 sec(!)
我的结论是从JDK 1.7调用的jlapack非常接近lapack的原生二进制性能.我使用了Linux发行版附带的lapack二进制库,并调用了dgesvd例程来获取U,S和VT矩阵.所有测试均在每次运行完全相同的矩阵上使用双精度完成(Octave除外).
免责声明 - 我不是线性代数方面的专家,不属于上述任何一个库,这不是一个严格的基准.这是一个"自制"测试,因为我有兴趣比较JDK 1.7到1.6的性能提升以及公共数学SVD到jlapack.
Jeigen https://github.com/hughperkins/jeigen
快速测试,通过乘以两个密集矩阵,即:
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();
Run Code Online (Sandbox Code Playgroud)
结果:
Jama: 4090 ms
Jblas: 1594 ms
Ojalgo: 2381 ms (using two threads)
Jeigen: 2514 ms
Run Code Online (Sandbox Code Playgroud)
小智 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%.
我是la4j(Java 线性代数)库的作者,这是我的观点。我已经在 la4j 上工作了 3 年(最新版本是 0.4.0 [2013 年 6 月 1 日]),直到现在我才可以开始进行性能分析和优化,因为我刚刚涵盖了所需的最低功能。所以,la4j 没有我想要的那么快,但我花了很多时间来改变它。
我目前正在将新版本的 la4j 移植到JMatBench平台。我希望新版本能够比以前的版本表现出更好的性能,因为我在 la4j 中做了一些改进,例如更快的内部矩阵格式、不安全的访问器和矩阵乘法的快速阻塞算法。
| 归档时间: |
|
| 查看次数: |
109084 次 |
| 最近记录: |