有点相关的问题,已经有一年了:任何JVM的JIT编译器是否会生成使用向量化浮点指令的代码?
前言:我正在尝试在纯Java中进行此操作(没有JNI到C++,没有GPGPU工作等)。 我已经进行了分析,大部分处理时间来自于此方法中的数学运算(可能是95%的浮点数学和5%的整数数学)。 我已经将所有Math.xxx()调用简化为足够好的近似值,因此现在大部分数学都是浮点乘法加上少量加法。
我有一些处理音频的代码。 我一直在进行微调,并且已经取得了巨大的进展。 现在,我正在研究手动循环展开,看看是否有任何好处(至少手动展开2个时,我看到了大约25%的改进)。 当尝试手动展开4个时(这已经变得非常复杂,因为我正在展开嵌套循环的两个循环),我想知道是否有任何方法可以提示jvm在运行时可以使用向量操作(例如SSE2,AVX等)。 每个音频样本可以完全独立于其他样本计算,这就是为什么我已经能够看到25%的改进(减少了对浮点计算的依赖)。
例如,我有4个浮点数,分别用于循环展开的4个部分计算值。 我如何声明和使用这些浮点数是否重要? 如果我将其设置为float[4],是否会提示jvm它们彼此不相关,而不是使用float,float,float,float,甚至是一个包含4个public float的类? 是否有一些我无意中做的事情会破坏我的代码被向量化的机会?
我有一些处理音频的代码。 我一直在进行微调,并且已经取得了巨大的进展。 现在,我正在研究手动循环展开,看看是否有任何好处(至少手动展开2个时,我看到了大约25%的改进)。 当尝试手动展开4个时(这已经变得非常复杂,因为我正在展开嵌套循环的两个循环),我想知道是否有任何方法可以提示jvm在运行时可以使用向量操作(例如SSE2,AVX等)。 每个音频样本可以完全独立于其他样本计算,这就是为什么我已经能够看到25%的改进(减少了对浮点计算的依赖)。
例如,我有4个浮点数,分别用于循环展开的4个部分计算值。 我如何声明和使用这些浮点数是否重要? 如果我将其设置为float[4],是否会提示jvm它们彼此不相关,而不是使用float,float,float,float,甚至是一个包含4个public float的类? 是否有一些我无意中做的事情会破坏我的代码被向量化的机会?
我在网上看到有关“正常”编写代码的文章,因为编译器/JVM知道常见模式以及如何进行优化,而偏离这些模式可能意味着较少的优化。然而,在这种情况下,即使将循环展开两次也不会像它所做的那样大幅提高性能,因此我想知道是否还有其他我可以做(或者至少不要做)来提高成功的机会。我知道编译器/JVM只会变得更好,因此我还要谨慎地避免做一些未来会对我造成伤害的事情。
编辑说明:将循环展开四次比将循环展开两次再增加了约25%的性能,因此我真的认为如果JVM支持它(或者已经在使用),矢量操作会在我的情况下有所帮助。
谢谢!