我正在开发一个主要是Java的项目。该应用程序非常耗费计算量(它执行几个数学运算,例如2048位数的取幂和乘法)。性能很重要,用户希望尽快获得结果。
最初,所有代码都是Java,但是由于性能原因(C中的某些部分和C ++中的某些部分),应用程序中计算密集程度最高的部分已在C和C ++中重新实现。
应用程序本身检测路径上是否有某些共享库文件可用,如果找到这些库然后使用它们,如果找不到它们,则一切都是用Java完成的。
Java应用程序使用JNI来调用本机代码。
C和C ++使用GMP库(https://gmplib.org)来执行数学运算。
目前,分发给用户的分发文件包括一个jar(包含已编译的Java代码),C和C ++源代码,以及用于编译C和C ++代码以及执行应用程序的脚本。 p>
用户必须执行的构建过程如下:
下载,编译和配置GMP。
将C代码编译为共享库文件(windows上的DLL,Linux上的.so),例如,在Linux上,用户执行:
gcc -fPIC -shared -O2 -o ../lib/libconnectorgmp.so -I $$ JAVA_HOME / include / -I $$ JAVA_HOME / include / linux -I包括NativeAdapter.c ../include/libgmp。一个
将C ++代码编译为共享库文件,例如,在Linux上,用户执行:
g ++ -fPIC -shared -O2 -o ../lib/libNativeLimMultiExpo.so -I $$ JAVA_HOME / include / -I $$ JAVA_HOME / include / linux -I include NativeLimMultiExpo.cpp MultiExponentiation.cpp MultiExponentiation.h。 ./include/libgmp.a
注意:
../include / libgmp.a.a是在步骤1中生成的文件。
.c,.cpp和.h文件是应用程序代码。
一旦用户执行了这些步骤,他们将拥有两个共享库文件,然后在调用Java应用程序时将它们包含在路径中。
此构建过程正常。生成和使用共享库时,性能通常比纯Java快5倍。
问题是,如果将库文件的编译版本分发给用户,是否会实现相同的性能。在这种情况下,将分发用于Windows和Linux的32位和64位库。
我想编译的GMP对象文件也将包含在这些库中,这样用户就不必执行当前构建过程的第1步。
一个很大的优势是用户必须执行更少的步骤,但我不知道性能是否会更低。
我想这个问题可以说是:"编译为一个架构"和#34;在机器上编译",在性能方面?
答案 0 :(得分:0)
使用非常特定编译器标志为特定机器的硬件编译代码原则上应该获得最佳性能。
然而在实践中我认为,当您在引擎盖下使用GMP时,大部分优化已经通过使用GMP完成。使用任何 GMP而不是Java的BigInteger的速度远远超过其他任何东西,这可能接近于无法测量的最佳值。
现代C / C ++编译器非常好地优化。把它们留给它。
Java和JNI可能会增加开销,如果性能如此重要,我会非常想要摆脱它。 JNI和Java带来了优化C / C ++的开销。换句话说,完全跳过Java并使用纯C / C ++。
我怀疑分发构建系统和源代码是您的描述。这有许多缺点,尤其是它迫使用户成为开发人员。例如,如果GMP发布了带有改进的新版本(这很可能),那么您的用户现在必须从新来源重建应用程序,或者只是忍受他们拥有的内容。如果发布了安全修补程序,也是如此。
我认为通常最好安装像GMP这样的通用库,以便以库分销商推荐的方式轻松升级和更换。
总的来说,获得表现:
完全抛弃Java,使用100%C / C ++
让编译器找出最佳优化方法(只需-O3)。
不要自己分发GMP。它提出了一个你不需要的问题。
一个小问题:
C中的某些部分和C ++中的某些部分
这不是我通常推荐的。选择一个或另一个。您实际上混合了三种不同的语言(使用Java),它只会产生潜在的问题。如果您正在使用C ++,那么在任何地方使用它都是我的建议。