Java与C++ - 光线追踪

4

我以Java为爱好项目创建了一个简单的光线追踪器,但是它很慢。虽然不是非常慢,但还是慢。我想知道是否可以使用更底层的语言,例如C或C ++,来获得性能提升,或者差异会微不足道,我应该继续改进"我的"算法?

8个回答

3

这要看情况。使用C/C++将使您能够访问Java无法实现的一些功能,例如SIMD(单指令多数据流)。

换句话说,我认为通常情况下,在C/C++中能够达到更好的效果,但需要付出一定的努力。首先进行所有基本的(数学/算法)优化。然后再进行微观优化。


“例如SIMD” - 现代JIT已经将代码向量化,因此如果他不使用编译器内置函数,差异可能会非常小。 - Voo
@Voo:这就是我说“但需要一些工作”的原因。而SIMD只是其中之一的例子。 - Mysticial
2
它可能无法像人类一样做得那么好,因为它必须猜测如何并行处理。如果我使用SIMD,我可能会使用OpenCL而不是CPU指令。 - zduny
你不仅可以在C++中使用SIMD,还能够在Java中编写8字节节点kd树的实现吗? - Sebastian Mach

3
我认为这个问题的答案是肯定的,非解释性语言在99.99%的情况下比在虚拟机下运行相同算法要快。 这就是说(在图像处理方面,我曾经在Java和C/C ++中工作过,在那里内存和时间很重要),我认为你应该首先尝试优化代码,以下是我的建议:
  • 使用分析器找到代码的瓶颈。有很多我们有时会忽略的东西可以通过这样的工具来揭示(例如类型转换,不必要的对象创建,应首先优化的最关键函数)。分析器应该是你的朋友。

然后(这里只是我在光线追踪中看到的一些例子):

  • 用查找表(只要你能)或近似函数替换tan / sin / cos
  • 尝试按数组而不是按样本处理数据
  • 尝试使用多个线程
现在这些东西“好”,但如果速度对你来说真的很关键,我不建议使用c或c++语言(即使你可以),而更应该专注于OpenCL。这可能是构建光线追踪引擎最适合的工具,并且最适应。想象一下,这里谈论的不是30%的改进,而更有可能是10,000%(快100倍)。这是一个Java接口:http://jogamp.org/jocl/www/祝你好运 :-)

如果你能够普遍地注意到JIT代码和由C++编译器生成的代码之间的区别,那么你要么使用编译器内置函数来执行两个编译器都无法完成的操作,要么测量语言规范强制使一种语言变慢的情况,或者是测量错误。而且后者很容易出错(或者说:正确地做起来非常困难)。无论如何:对于光线追踪,采用GPU解决方案显然更优,而在现代CPU上使用查找表可能并不是一个好主意;-) - Voo
1
嗯,我不太明白最后一点:优化大多数情况下(甚至可以说总是)是内存与CPU之间的权衡。查找表只是其中之一:这只是一种手动缓存(而您肯定知道缓存对于使某些东西平稳运行非常重要;-))。 - Flavien Volken
2
这要看情况。内存与CPU之间的权衡是众所周知的,但在这种情况下,重新计算正弦值可能比在表中查找更快 - 特别是如果有大量计算正在进行。该表还会从缓存中驱逐一些其他有用的数据,或者本身可能被驱逐(对性能也不利)。因此,这是需要进行基准测试以确保的事情。 - Voo

3

AMD刚刚发布了一个名为Aparapi的开源项目,它可以在运行时将Java字节码转换为OpenCL。如果您的代码无法转换为OpenCL(存在限制),或者您没有可用的OpenCL,则代码将在线程池中运行。

可能非常适合您的需求。

http://aparapi.googlecode.com


如果它能够很好地工作,那就令人印象深刻,这是一个有趣的发现+1,你在回答中发布了一个有用的摘要来补充和配合链接。 - Flexo

2

由于你只了解你的实现细节,这个问题很难回答。如果你的方法主要是数学计算,那么Java在幕后进行各种优化,我认为切换到C++不会带来太多改进。

如果你使用了大量外部库,并且根据显示光线追踪结果的方法,可能会通过移动到基于C的实现而得到改进。


我不使用任何外部库,而且显示结果实际上非常快。最耗时间的是生成结果。如果需要,我可以包含来自VisualVM的屏幕截图以提供帮助... - zduny
C/C++中也有很多数学库。 - Rob

2

如果您使用低效算法,并且学习新语言会带来很多麻烦,那么转换到C/C++只会给您带来微小的收益。适当编写的Java可以实现与类似的C/C++代码大致相同的速度,达到非商业用途光线追踪器的要求。我假设光线追踪器现在已经功能完备,因此建议您学习如何使用分析工具来检测代码中的瓶颈。请记住80/20规则(或者是90/10、75/25之类的规则),即程序80%的时间在运行其20%的代码。

优化算法通常比更换编程语言能提供更好的性能提升。


2
光线追踪的效率取决于加速结构。使用 C++ 而不是 Java 肯定会有所帮助。然而,如果你缺乏如 BVH 或 Kd 树这样的高效结构,无论你使用哪种语言,你的光线追踪器都会很慢。
如果只是业余爱好,建议继续使用 Java。如果你想加载像斯坦福佛像或泰国佛像这样复杂的模型,那么你肯定应该转向 C++ 并开始阅读“基于物理的渲染”: http://www.pbrt.org/ 你可以在 http://pbrt.org/pbrt-2ed-chap4.pdf 上免费下载第四章。
简而言之,你可以根据项目的目标来回答你的问题。简单的业余爱好=继续使用 Java。具有复杂模型的实时光线追踪=C++。

1

几年前我用Java做了一个简单的光线追踪器。对于非常简单的网格(著名的茶壶3D网格和兔子3D网格),我可以使用实时渲染进行计算。所以我想你也可以做到=)

如果这只是业余爱好,请坚持使用Java,没有必要转向C ++。而且,不要着眼于更改语言,而是考虑如何改进您的代码(例如在log(n)时间内查找被光线击中的三角形,多线程编程等等)。


BSP?哪个分辨率?带或不带抗锯齿?您使用了什么硬件(这样我才能进行比较)。 - zduny
是的,BSP,分辨率必须很好,网格非常小(斯坦福兔子有69,451个三角形),没有抗锯齿,但我很确定我们使用了简单的Phong反射模型(茶壶看起来圆润,没有棱角)。电脑规格未知,但你可以猜测,那是三年前,在一个公共校园电脑上(可能是一台没有显卡的E6200)。 - B. Decoster

-1

我猜你会发现使用C或C++可以获得显著的性能提升。你可以尝试使用像this这样的工具来转换你的代码。


我不认为简单的代码翻译能够带来任何显著的改进。 - zduny
因为使用优化编译C或C++可能会产生比HotSpot更快的机器代码,但这只是一个大的可能性。有许多因素可以改善或降低两种语言的性能。 - Daniel Pereira

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接