关于Java中重度数学计算的问题

时间:2022-09-06 13:25:28

I am using Java in my project which does a lot of mathematical calculations. In the next iteration of the project, some more calculations will be added. From my knowledge of Java, I suspect that this will cause performance issues. Is it a wise decision to delegate the heavy calculations to a low level language like Fortran or C? I can fire native calls to communicate with the low level languages. Java will take the control once the calculations are performed by Fortran or C. Will this better the performance?

我在我的项目中使用Java,它进行了大量的数学计算。在项目的下一次迭代中,将添加一些更多的计算。根据我对Java的了解,我怀疑这会导致性能问题。将繁重的计算委托给Fortran或C等低级语言是明智的决定吗?我可以触发本机调用与低级语言进行通信。一旦Fortran或C执行计算,Java将采取控制措施。这会改善性能吗?

7 个解决方案

#1


9  

Be careful not to underestimate modern Java VMs. The first generation ones were awesomely slow, especially at floating-point arithmetic, but modern ones are very quick indeed.

注意不要低估现代Java VM。第一代的速度非常慢,特别是在浮点运算时,但现代的确非常快。

Having said that, other options are probably going to be quicker.

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

To be sure, you should run some benchmarks. Don't assume one is going to faster than the other, get some concrete performance measurements and make your decision on that basis.

当然,你应该运行一些基准测试。不要假设一个比另一个更快,得到一些具体的性能测量并在此基础上做出决定。

Also consider whether the extra performance (if any) of a "native" solution is worth the extra hassle of writing it and integrating it.

还要考虑“本机”解决方案的额外性能(如果有的话)是否值得编写和集成它的额外麻烦。

#2


6  

Integer and floating point math as such in Java are handed right down to the hardware, and the calculations as such are in principle not slower than in C, say, or FORTRAN. The library routines for stuff like transcendental functions (sin(), sqrt(), log(), etc) are in fact implemented in C, so again there's no good reason to look to other libraries.

Java中的整数和浮点数学都是直接传递给硬件的,因此这样的计算原则上不会慢于C,比如说或FORTRAN。事实上,像超常函数(sin(),sqrt(),log()等)的库例程实现在C中,所以再没有理由去寻找其他库。

There's some information I wish your question gave us. You mention that there's a lot of calculation going on, and that's number crunching. But you don't tell us anything about how those numbers are organized and accessed. This is probably interesting and useful information. If you're using intricate object structures to hold your data, accessing those structures is going to take time. If your results create new objects, that's also expensive. If you use arrays, those are also objects. Multi-dimensional arrays in Java are arrays of arrays, and indexing through multiple dimensions may resolve to object references which are slower than in other languages. Though I don't have benchmarks to prove it, I suspect you might be better off to replace multi-dimensional arrays with one-dimensional arrays and a bit of "manual" index calculation. You are certainly better off using fixed-size arrays, perhaps dimensioned with a bit of slack, rather than creating and discarding new arrays for each calculation. Finally, many of the object oriented tricks to make your program's structure more "elegant" and "flexible" tend to introduce a lot of unnecessary object orientation with attendant slowdowns. Primitive but simple is usually faster.

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

A very simple optimization might be to simply use the -server option of your JVM (if that's available) to get the benefit of more pre-compilation, if you're not already doing that.

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

I second other folks' recommendation that you profile your calculations, though, before you go blindly re-architecting your program. There may be bottlenecks in surprising places.

然而,在你盲目地重新设计你的程序之前,我第二个人建议你描述你的计算。令人惊讶的地方可能存在瓶颈。

#3


3  

Can you think of making use of parallel algorithms. It may or may not be applicable in your case but thought of pointing it out.

你能想到使用并行算法吗?它可能适用于您的情况,也可能不适用,但想到指出它。

#4


1  

It depends on two factors:

这取决于两个因素:

  1. You should remember that the JNI calls will have a cost. If you can have your whole calculation to C, that overhead can become negligible, and you may gain some performance. Otherwise, if you're going to go back and forth between C and Java, you don't stand much of a chance of improving your performance.
  2. 您应该记住,JNI调用会有成本。如果您可以将整个计算结果用于C,那么开销可以忽略不计,并且您可以获得一些性能。否则,如果您要在C和Java之间来回切换,那么您就没有太大机会提高性能。
  3. Say you'll have a function f() that does the calculation. You should first determine if the performance you can get from C is indeed superior to that in Java. I vaguely recall some article benchmarking C and Java that actually claimed that Java did a better job in terms of mathematical calculations. But in any case I'd benchmark both - at least a subset of them.
  4. 假设你有一个函数f()进行计算。您首先应该确定从C获得的性能是否确实优于Java。我隐约回想起一些文章对C和Java进行了基准测试,实际上他们认为Java在数学计算方面做得更好。但无论如何,我都会对两者进行基准测试 - 至少是其中的一部分。

#5


1  

You should also play with various VM parameters. Run your program in server mode, this way JIT will produce better code, experiment with different garbage collectors, turn on escape analysis (might be better to use JDK 7 with that).

您还应该使用各种VM参数。在服务器模式下运行程序,这样JIT将生成更好的代码,尝试使用不同的垃圾收集器,打开转义分析(可能更好地使用JDK 7)。

This paper may help you tune your program to use the best of JVM.

本文可以帮助您调整程序以使用最好的JVM。

If you decide to choose the native path, use JNA, it's just much easier, especially if all your calculations will be in one method call.

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

#6


1  

All the comments so far are excellent. I would agree that native code should be a last step.

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

Parallelizing would be worth investigating.

并行化是值得研究的。

So would using another algorithm, depending on what you're doing.

那么使用另一种算法,取决于你正在做什么。

No one has suggested that you profile the code yet to find out where the time is being spent. Before embarking on any modifications I'd get some data to find out exactly what's being done and where. It'll guide your decisions better than guessing.

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

#7


0  

I would suggest to wait and see... Implement in Java as you normally do and then measure the performance, is it good, acceptable or bad?

我建议你拭目以待......像往常一样用Java实现,然后测量性能,它是好的,可接受的还是坏的?

As Skaffman saids moderns JVMs have high performance and thanks to the JIT compiler they're in many cases faster than native C.

正如Skaffman所说,现代JVM具有高性能,并且由于JIT编译器,它们在许多情况下比本机C更快。

This article shows some comparisons between Java and C calculations, it's also an example that using tha latest JVM version is a good idea performance wise.

本文展示了Java和C计算之间的一些比较,它也是一个使用最新JVM版本的一个例子,性能明智。

#1


9  

Be careful not to underestimate modern Java VMs. The first generation ones were awesomely slow, especially at floating-point arithmetic, but modern ones are very quick indeed.

注意不要低估现代Java VM。第一代的速度非常慢,特别是在浮点运算时,但现代的确非常快。

Having said that, other options are probably going to be quicker.

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

To be sure, you should run some benchmarks. Don't assume one is going to faster than the other, get some concrete performance measurements and make your decision on that basis.

当然,你应该运行一些基准测试。不要假设一个比另一个更快,得到一些具体的性能测量并在此基础上做出决定。

Also consider whether the extra performance (if any) of a "native" solution is worth the extra hassle of writing it and integrating it.

还要考虑“本机”解决方案的额外性能(如果有的话)是否值得编写和集成它的额外麻烦。

#2


6  

Integer and floating point math as such in Java are handed right down to the hardware, and the calculations as such are in principle not slower than in C, say, or FORTRAN. The library routines for stuff like transcendental functions (sin(), sqrt(), log(), etc) are in fact implemented in C, so again there's no good reason to look to other libraries.

Java中的整数和浮点数学都是直接传递给硬件的,因此这样的计算原则上不会慢于C,比如说或FORTRAN。事实上,像超常函数(sin(),sqrt(),log()等)的库例程实现在C中,所以再没有理由去寻找其他库。

There's some information I wish your question gave us. You mention that there's a lot of calculation going on, and that's number crunching. But you don't tell us anything about how those numbers are organized and accessed. This is probably interesting and useful information. If you're using intricate object structures to hold your data, accessing those structures is going to take time. If your results create new objects, that's also expensive. If you use arrays, those are also objects. Multi-dimensional arrays in Java are arrays of arrays, and indexing through multiple dimensions may resolve to object references which are slower than in other languages. Though I don't have benchmarks to prove it, I suspect you might be better off to replace multi-dimensional arrays with one-dimensional arrays and a bit of "manual" index calculation. You are certainly better off using fixed-size arrays, perhaps dimensioned with a bit of slack, rather than creating and discarding new arrays for each calculation. Finally, many of the object oriented tricks to make your program's structure more "elegant" and "flexible" tend to introduce a lot of unnecessary object orientation with attendant slowdowns. Primitive but simple is usually faster.

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

A very simple optimization might be to simply use the -server option of your JVM (if that's available) to get the benefit of more pre-compilation, if you're not already doing that.

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

I second other folks' recommendation that you profile your calculations, though, before you go blindly re-architecting your program. There may be bottlenecks in surprising places.

然而,在你盲目地重新设计你的程序之前,我第二个人建议你描述你的计算。令人惊讶的地方可能存在瓶颈。

#3


3  

Can you think of making use of parallel algorithms. It may or may not be applicable in your case but thought of pointing it out.

你能想到使用并行算法吗?它可能适用于您的情况,也可能不适用,但想到指出它。

#4


1  

It depends on two factors:

这取决于两个因素:

  1. You should remember that the JNI calls will have a cost. If you can have your whole calculation to C, that overhead can become negligible, and you may gain some performance. Otherwise, if you're going to go back and forth between C and Java, you don't stand much of a chance of improving your performance.
  2. 您应该记住,JNI调用会有成本。如果您可以将整个计算结果用于C,那么开销可以忽略不计,并且您可以获得一些性能。否则,如果您要在C和Java之间来回切换,那么您就没有太大机会提高性能。
  3. Say you'll have a function f() that does the calculation. You should first determine if the performance you can get from C is indeed superior to that in Java. I vaguely recall some article benchmarking C and Java that actually claimed that Java did a better job in terms of mathematical calculations. But in any case I'd benchmark both - at least a subset of them.
  4. 假设你有一个函数f()进行计算。您首先应该确定从C获得的性能是否确实优于Java。我隐约回想起一些文章对C和Java进行了基准测试,实际上他们认为Java在数学计算方面做得更好。但无论如何,我都会对两者进行基准测试 - 至少是其中的一部分。

#5


1  

You should also play with various VM parameters. Run your program in server mode, this way JIT will produce better code, experiment with different garbage collectors, turn on escape analysis (might be better to use JDK 7 with that).

您还应该使用各种VM参数。在服务器模式下运行程序,这样JIT将生成更好的代码,尝试使用不同的垃圾收集器,打开转义分析(可能更好地使用JDK 7)。

This paper may help you tune your program to use the best of JVM.

本文可以帮助您调整程序以使用最好的JVM。

If you decide to choose the native path, use JNA, it's just much easier, especially if all your calculations will be in one method call.

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

#6


1  

All the comments so far are excellent. I would agree that native code should be a last step.

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

Parallelizing would be worth investigating.

并行化是值得研究的。

So would using another algorithm, depending on what you're doing.

那么使用另一种算法,取决于你正在做什么。

No one has suggested that you profile the code yet to find out where the time is being spent. Before embarking on any modifications I'd get some data to find out exactly what's being done and where. It'll guide your decisions better than guessing.

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

#7


0  

I would suggest to wait and see... Implement in Java as you normally do and then measure the performance, is it good, acceptable or bad?

我建议你拭目以待......像往常一样用Java实现,然后测量性能,它是好的,可接受的还是坏的?

As Skaffman saids moderns JVMs have high performance and thanks to the JIT compiler they're in many cases faster than native C.

正如Skaffman所说,现代JVM具有高性能,并且由于JIT编译器,它们在许多情况下比本机C更快。

This article shows some comparisons between Java and C calculations, it's also an example that using tha latest JVM version is a good idea performance wise.

本文展示了Java和C计算之间的一些比较,它也是一个使用最新JVM版本的一个例子,性能明智。