C 就性能而言,就共享库文件而言,是;为一个架构而编译;无异于;在机器上编译;?

C 就性能而言,就共享库文件而言,是;为一个架构而编译;无异于;在机器上编译;?,c,performance,java-native-interface,shared-libraries,gmp,C,Performance,Java Native Interface,Shared Libraries,Gmp,我正在从事一个主要是Java的项目。该应用程序的计算量非常大(它对2048位数字执行多项数学运算,如指数运算和乘法运算)。性能很重要,用户希望尽快获得结果 最初,所有代码都是java,但是应用程序中计算量最大的部分在C和C++中都是出于性能原因(C++中的某些部分和C++中的某些部分)重新实现的。 应用程序本身检测某些共享库文件是否在路径上可用,如果找到这些库,则使用它们,如果找不到,则一切都用Java完成 Java应用程序使用JNI调用本机代码 C和C++使用GMP库()进行数学运算。 目前

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

最初,所有代码都是java,但是应用程序中计算量最大的部分在C和C++中都是出于性能原因(C++中的某些部分和C++中的某些部分)重新实现的。 应用程序本身检测某些共享库文件是否在路径上可用,如果找到这些库,则使用它们,如果找不到,则一切都用Java完成

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

C和C++使用GMP库()进行数学运算。

目前分发给用户的分发文件包括jar(包含编译的java代码)、C和C++源代码以及编译C和C++代码的脚本,并执行应用程序。 用户必须执行的构建过程如下:

  • 下载、编译和配置GMP

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

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

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

    g++-fPIC-shared-O2-o../lib/libNativeLimMultiExpo.so-I$$JAVA_HOME/include/-I$$JAVA_HOME/include/linux-I include NativeLimMultiExpo.cpp multiexpo.cpp MultiExponentiation.h../include/libgmp.a

    注:

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

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

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

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

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

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

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

    我想问题可以表述为:“是为架构编译的”在性能方面与“在机器上编译的”一样好?

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

    然而,在实践中,我认为,当您在幕后使用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++,到处使用它是我的建议。

    我认为强迫用户编译一些东西不会吸引他们(取决于程序的目的)。在我看来,分发已经编译好的文件不会影响速度。例如,我正在开发(这也需要尽可能快)。我正在分发普通二进制文件,因为经过一些实验后,我发现在用户机器上编译程序并不能提高速度。@mustaccio使用相同的编译器使用相同的标志编译相同的源代码,并在理论上与相同的库链接,应该会产生相同的目标代码,不管编译是在哪台机器上完成的。不,不会的。不同的机器(甚至x86)可以而且确实支持不同的指令集。在不同的x86机器上使用GCC和
    -march=native
    进行编译可以生成在许多其他机器上无法运行的截然不同的二进制文件。这只是保持在x86世界中。这只是获得成功的一种方法