c-就性能而言,就共享库文件而言,是“;为一个体系结构而编译”;与“;在机器上编译”;



我正在做一个主要是Java的项目。该应用程序的计算量非常大(它对2048位数字执行多项数学运算,如幂运算和乘法运算)。性能很重要,用户希望尽快得到结果。

最初,所有的代码都是Java,但由于性能原因,应用程序中计算量最大的部分已在C和C++中重新实现(有些部分在C中,有些部分在C++中)。

应用程序本身检测某些共享库文件是否在路径上可用,如果找到这些库,则使用它们;如果找不到,则一切都用Java完成。

Java应用程序使用JNI来调用本机代码。

C和C++中使用GMP库(https://gmplib.org)以执行数学运算。

目前,分发给用户的分发文件包括一个jar(包含编译的Java代码)、C和C++源代码,以及编译C和C++代码和执行应用程序的脚本。

用户必须执行的构建过程如下:

  1. 下载、编译和配置GMP。

  2. 将C代码编译为共享库文件(windows上的dll,linux上的.so),例如,在linux上,用户执行:

    gcc-fPIC-共享-O2-o/lib/libconnectorgmp.so-I$$JAVA_HOME/include/-I$$JAVA_HOME/include/linux-I include NativeAdapter.c./include-libgmp.a

  3. 将C++代码编译为共享库文件,例如,在Linux上,用户执行:

    g++-fPIC-共享-O2-o/lib/libNativeLimMultiExpo.so-I$$JAVA_HOME/include/-I$$JAVA_HOME/include/linux-I include NativeLim MultiExpo.cpp MultiExponention.cpp Multiexponention.h../include/libgmp.a

注:

  1. /include/libgmp.a.a是在步骤1中生成的一个文件。

  2. .c、.cpp和.h文件是应用程序代码。

一旦用户执行了这些步骤,他们将拥有两个共享库文件,然后在调用Java应用程序时将它们包含在路径中。

此构建过程运行良好。当生成和使用共享库时,性能通常比纯Java快5倍左右。

问题是,如果将库文件的编译版本分发给用户,是否会获得相同的性能。在这种情况下,将分发用于Windows和Linux的32位和64位库。

我想编译后的GMP对象文件也会包含在这些库中,这样用户也不必执行当前构建过程的第1步。

一个很大的优势是用户必须执行更少的步骤,但我不知道性能是否会更低。

我想这个问题可以说是:就性能而言,"为架构编译"one_answers"在机器上编译"一样好吗?

使用非常特定的编译器标志为特定机器的硬件编译代码原则上应该获得最佳性能。

然而,在实践中,我认为,当你在幕后使用GMP时,大部分优化已经通过使用GMP完成了。使用anyGMP而不是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++,我建议你在任何地方都使用它。

相关内容

最新更新