如何编写代码以提示JVM使用向量操作?

一些相关的问题和一年之久: JVM的JIT编译器是否生成使用向量化浮点指令的代码?

前言:我试图在纯java中执行此操作(没有JNI到C ++,没有GPGPU工作等等)。 我已经进行了分析,并且大部分处理时间来自此方法中的数学运算(可能是95%的浮点数学运算和5%的整数运算)。 我已经将所有Math.xxx()调用减少到足够好的近似值,因此大部分数学运算现在都是浮点数乘以一些加法。

我有一些处理音频处理的代码。 我一直在进行调整,并且已经获得了巨大的收益。 现在我正在研究手动循环展开以查看是否有任何好处(至少手动展开2,我看到大约25%的改进)。 在尝试手动展开4时(由于我展开嵌套循环的两个循环,这开始变得非常复杂)我想知道是否有任何我可以做的提示到jvm在运行时它可以使用向量操作(例如SSE2,AVX等……)。 音频的每个样本都可以完全独立于其他样本计算,这就是为什么我已经能够看到25%的改进(减少浮点计算的依赖性)。

例如,我有4个浮点数,一个用于循环的4个展开中的每一个,以保存部分计算的值。 我如何声明和使用这些浮子很重要吗? 如果我把它变成一个浮点数[4],它会向jvm暗示它们彼此无关,而不是浮动,浮动,浮动,浮动甚至是一类4个公共浮标? 有什么我可以做的没有意义,这会杀死我的代码被矢量化的机会?

我在网上看到有关“正常”编写代码的文章,因为编译器/ jvm知道常见模式以及如何优化它们并且偏离模式可能意味着更少的优化。 但至少在这种情况下,我不会期望将循环展开2以提高性能,因为我知道是否还有其他任何我可以做(或者至少不做)来帮助我机会。 我知道编译器/ jvm只会变得更好所以我也要警惕做将来会伤害我的事情。

为好奇者编辑:在2次展开时,将4次性能提升另外约25%,因此我认为如果jvm支持它(或者可能已经使用它们),向量操作将对我的情况有所帮助。

谢谢!

我怎么能..audio processing..pure java(没有JNI到C ++,没有GPGPU工作等等)..使用向量操作(例如SSE2,AVX等……)

Java是高级语言(Java中的一条指令生成许多硬件指令),这是一种设计(例如垃圾收集器内存管理),不适合实时操作高数据量的任务。

通常存在针对特定角色(例如图像处理或语音识别 )优化的特殊硬件,其多次通过若干简化的处理流水线进行并行化。

这类任务还有特殊的编程语言,主要是硬件描述语言和汇编语言 。

即使是C ++(被认为是快速语言)也不会自动为您使用一些超级优化的硬件操作。 它可能只是在某些地方内联几种手工制作的汇编语言方法之一。

所以我的答案是, “可能没有办法”指示JVM对你的代码使用一些硬件优化(例如SSE ),即使有一些,Java语言运行时仍会有太多其他因素会减慢你的代码。

使用为此任务设计的低级语言,并将其链接到Java以获得高级逻辑。

编辑:根据评论添加更多信息

如果你确信高级“一次编写一次运行”语言运行时肯定也应该为你做很多低级优化,并自动将你的高级代码转换为优化的低级代码……那么JIT编译器优化的方式取决于Java虚拟机的实现 。 他们中有很多人。

对于Oracle JVM(HotSpot),您可以通过下载源代码开始查找答案,文本SSE2出现在以下文件中:

  • OpenJDK的/热点/ src目录/ CPU / 86 / VM / assembler_x86.cpp
  • OpenJDK的/热点/ src目录/ CPU / 86 / VM / assembler_x86.hpp
  • OpenJDK的/热点/ src目录/ CPU / 86 / VM / c1_LIRGenerator_x86.cpp
  • OpenJDK的/热点/ src目录/ CPU / 86 / VM / c1_Runtime1_x86.cpp
  • OpenJDK的/热点/ src目录/ CPU / 86 / VM / sharedRuntime_x86_32.cpp
  • OpenJDK的/热点/ src目录/ CPU / 86 / VM / vm_version_x86.cpp
  • OpenJDK的/热点/ src目录/ CPU / 86 / VM / vm_version_x86.hpp
  • OpenJDK的/热点/ src目录/ CPU / 86 / VM / x86_32.ad
  • OpenJDK的/热点/ src目录/ OS_CPU / linux_x86 / VM / os_linux_x86.cpp
  • OpenJDK的/热点/ src目录/股/ VM / C1 / c1_GraphBuilder.cpp
  • OpenJDK的/热点/ src目录/股/ VM / C1 / c1_LinearScan.cpp
  • OpenJDK的/热点/ src目录/股/ VM /运行/ globals.hpp

它们使用的是C ++和汇编语言,因此无论如何您都必须学习一些低级语言才能阅读它们。

即使有+500赏金,我也不会那么深。 恕我直言,基于错误的假设,这个问题是错误的

Hotspot上的SuperWord优化是有限的,非常脆弱。 有限,因为它们通常落后于C / C ++编译器所提供的,并且易碎,因为它们依赖于特定的循环形状(并且仅支持某些CPU)。

我知道你想在任何地方运行一次。 听起来你已经有了一个纯Java解决方案。 您可能想要考虑已知流行平台的可选实现,以补充该实现“在某些地方快速”,这可能已经是真实的。

使用某些代码很难给出更具体的反馈。 我建议你把这个循环问题呈现在JMH基准测试中。 这使得分析和讨论变得容易。

看起来在Java 8/9中进行了大量的SIMD / SSE优化。