2010-11-13 71 views
4

我在我的项目中使用了Java,它进行了大量的数学计算。在项目的下一次迭代中,将会添加更多的计算。从我对Java的知识中,我怀疑这会导致性能问题。将繁重的计算委托给像Fortran或C这样的低级语言是明智的决定吗?我可以通过本机调用来与低级语言进行通信。一旦Fortran或C执行计算,Java将采取控制。 性能会更好吗?关于Java中的重数学计算的问题

回答

8

小心不要低估现代Java虚拟机。第一代速度非常慢,特别是在浮点运算上,但现代的速度确实非常快。

话虽如此,其他选择可能会更快。

可以肯定,你应该运行一些基准测试。不要以为其中一个会比另一个更快,得到一些具体的性能指标并在此基础上做出决定。

另外考虑一个“原生”解决方案的额外性能(如果有的话)是否值得写入它并整合它的额外麻烦。

+0

你说得对,本机代码会花费额外的时间编码和集成。目前计算需要12分钟,添加新计算可能需要14分钟。我的目标是把它降到8-9分钟。 – Sid 2010-11-13 11:37:56

+4

另外请注意,如果你在JNI中复制数据,那么这里还有一个重大的发现。我参与过的大量数字代码也涉及大量数据集,所以IO受限(通过CPU和内存之间的路径)而不是CPU受限制,并且混合使用Java和本机代码会使情况变得更糟。 – 2010-11-13 12:23:26

1

这取决于两个因素:

  1. 你应该记住,JNI调用需要一定费用。如果可以将整个计算结果转换为C,那么开销可能变得微不足道,并且您可能会获得一些性能。否则,如果你要在C和Java之间来回切换,你不会有很大的提高性能的机会。
  2. 假设你有一个函数f()来计算。您应该首先确定从C获得的性能是否优于Java。我隐约记得一些基准测试C和Java的文章,它们实际上声称Java在数学计算方面做得更好。但无论如何,我会对两者进行基准测试 - 至少是其中的一部分。
+0

我的想法是将所有计算移到C或Fortran以避免多个本地调用调用。 – Sid 2010-11-13 11:40:00

0

我会建议等着瞧...按照通常的方式用Java实现,然后衡量性能,是好的,可接受的还是不好的?

由于Skaffman甾体抗炎药现代人的JVM具有高性能和感谢JIT编译器他们在许多情况下比本地C.

This article显示Java和C计算之间的一些比较,它也是一个例子使用最新的JVM版本是一个不错的主意。

+0

我测量过的表现并不是很好。目前需要12分钟才能完成计算。我使用了一些多线程。我需要把它降到8分钟。 – Sid 2010-11-13 11:39:11

+0

-1,除非您编辑答案以包含至少一个同等评审的重数字Java代码示例,其速度明显快于C.通常,等同的Java代码最好保持得相当好,而Java *系统通常会以更快的速度结束花更少的时间修复错误并有更多时间进行分析。 – 2010-11-13 11:44:32

+0

添加链接。有很多类似的文章和基准,有人会说C更快,有些人会说相反。我的主要观点是,Java有一个缓慢的声誉,现在它不是真的,因为它通常基于10年前JVM的表现。 – Uhlen 2010-11-13 12:12:32

6

Java中的整数和浮点数学运算直接传递给硬件,原则上计算速度不会低于C或FORTRAN。像超验函数(例如sin(),sqrt(),,log()等等)的库例程实际上是用C实现的,所以再次没有理由去查看其他库。

我希望你的问题给我们提供了一些信息。你提到有很多计算正在进行,这就是数字计算。但是你不会告诉我们这些数字是如何组织和访问的。这可能是有趣和有用的信息。如果您使用复杂的对象结构来保存数据,访问这些结构将需要时间。如果你的结果创建新的对象,那也很昂贵。如果你使用数组,那些也是对象。Java中的多维数组是数组的数组,并且通过多维索引可能会解析为比其他语言更慢的对象引用。虽然我没有基准来证明它,但我怀疑用一维数组和一些“手动”索引计算替代多维数组可能会更好。当然,使用固定大小的数组可能会更好,可能会有一些松散的尺寸,而不是为每次计算创建和丢弃新数组。最后,许多面向对象的技巧让你的程序结构更“优雅”和“灵活”,往往会引入大量不必要的面向对象,伴随着服务员的减速。原始但简单通常更快。

一个非常简单的优化可能是简单地使用JVM的-server选项(如果有的话),以获得更多预编译的好处,如果您还没有这样做。

然而,在你盲目地重新设计你的程序之前,第二其他人的建议是你对你的计算进行剖析。在令人惊讶的地方可能会遇到瓶颈。

3

您可以考虑使用并行算法。它可能会或可能不适用于你的情况,但想到指出它。

+1

这是一个很好的建议,我希望我能想到它。如果OP的盒子中有2个或更多的CPU核心,并且任务可以被分割成并行任务,他几乎可以直接将其计算时间减少(几乎)2或更多,而不会显着改变他的程序或使用外部的外语代码。 – 2010-11-13 12:56:00

1

你也应该玩各种VM参数。以服务器模式运行程序,这样JIT将生成更好的代码,使用不同的垃圾收集器进行实验,打开逃逸分析(可能更适合使用JDK 7)。

This paper可能会帮助您调整程序以使用最好的JVM。

如果您决定选择本机路径,请使用JNA,这样会更容易,尤其是如果您的所有计算都在一次方法调用中。

1

到目前为止所有的评论都非常好。我同意本地代码应该是最后一步。

并行化是值得研究的。

所以会使用另一种算法,这取决于你在做什么。

没有人建议您对代码进行简介以找出所花费的时间。在开始任何修改之前,我会获得一些数据以确切了解正在做什么和在哪里。它会比猜测更好地指导你的决定。