java16学习笔记-Vector API
提供孵化器模块jdk.incubator.vector的初始迭代,以表示向量计算,该向量计算在运行时可靠地编译为支持的CPU架构上的最佳向量硬件指令,从而实现优于等效标量计算的性能
目标
向量计算由对向量的一系列操作组成。向量包括(通常)固定的标量值序列,其中标量值对应于硬件定义的向量通道的数量。应用于具有相同通道数的两个向量的二进制运算,对于每个通道,将对每个向量的相应两个标量值应用等效标量运算。这通常被称为单指令多数据(SIMD)。
矢量运算表示一种并行程度,可以在单个CPU周期内执行更多的工作,从而显著提高性能。例如,给定两个向量,每个向量覆盖八个整数序列(八个通道),则可以使用单个硬件指令将这两个向量加在一起。向量加法硬件指令对十六个整数进行操作,执行八次整数加法,而通常对两个整数进行一次整数加法所需的时间。
HotSpot支持自动矢量化,其中标量操作被转换为超字操作,然后映射到矢量硬件指令。可转换标量操作的集合是有限的,并且容易受到代码形状变化的影响。此外,可能仅利用可用向量硬件指令的子集来限制生成代码的性能。
希望编写可可靠转换为超字操作的标量操作的开发人员需要了解HotSpot的自动矢量化支持及其局限性,以实现可靠和可持续的性能。
在某些情况下,开发人员可能无法编写可转换的标量操作。例如,HotSpot不转换用于计算数组哈希码的简单标量操作(请参阅JDK源代码中的Arrays::hashCode方法实现),也不能自动矢量化代码以按字典比较两个数组(这就是为什么添加了一个内部函数来执行字典比较,请参阅8033148)。
Vector API旨在通过提供一种用Java编写复杂矢量算法的机制来解决这些问题,使用HotSpot中预先存在的矢量化支持,但使用一个用户模型,使矢量化更加可预测和稳健。手工编码的向量循环可以表达高性能算法(如矢量化的hashCode或专门的数组比较),而自动矢量器可能永远无法优化这些算法。这种显式向量化API可能适用于许多领域,如机器学习、线性代数、密码学、金融和JDK本身的使用。
发展历史
JEP 338: Vector API (Incubator) java16 第一次孵化
JEP 414: Vector API (Second Incubator) java17 第二次孵化
JEP 417: Vector API (Third Incubator) java18 第三次孵化
JEP 426: Vector API (Fourth Incubator) java19 第四次孵化
JEP 438: Vector API (Fifth Incubator) java20 第五次孵化
JEP 448: Vector API (Sixth Incubator) java21 第六次孵化
JEP 460: Vector API (Seventh Incubator) java22 第七次孵化
JEP 469: Vector API (Eighth Incubator) java23 第八次孵化
JEP 489: Vector API (Ninth Incubator) java24 第九次孵化
JEP 508: Vector API (Tenth Incubator) java25 第十次孵化
代码示例
void vectorComputation(float[] a, float[] b, float[] c) {for (int i = 0; i < a.length; i += SPECIES.length()) {// VectorMask<Float> m;var m = SPECIES.indexInRange(i, a.length);// FloatVector va, vb, vc;var va = FloatVector.fromArray(SPECIES, a, i, m);var vb = FloatVector.fromArray(SPECIES, b, i, m);var vc = va.mul(va).add(vb.mul(vb)).neg();vc.intoArray(c, i, m);}
}
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;void vectorComputation(float[] a, float[] b, float[] c) {int i = 0;int upperBound = SPECIES.loopBound(a.length);for (; i < upperBound; i += SPECIES.length()) {// FloatVector va, vb, vc;var va = FloatVector.fromArray(SPECIES, a, i);var vb = FloatVector.fromArray(SPECIES, b, i);var vc = va.mul(va).add(vb.mul(vb)).neg();vc.intoArray(c, i);}for (; i < a.length; i++) {c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;}
}
以上代码复制的官方示例代码,但是笔者尝试各种方法都没办法编译通过,从JDK16到24都试了个遍。