import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorOperators; import jdk.incubator.vector.VectorSpecies; /** * JEP 537, Vector API (twelfth incubator). The same source and the same class file run on JDK 26 * (eleventh incubator, JEP 529) and JDK 27, because the public API did not change between them: * docs/output/50-vector-api-surface.txt is the javap diff that shows it. For what the API is and * how to use it well, see the companion guide to JEP 537 on ankurm.com. * Run with --add-modules jdk.incubator.vector. */ public class VectorDemo { static final VectorSpecies SPECIES = FloatVector.SPECIES_PREFERRED; static float scalarDot(float[] a, float[] b) { float sum = 0; for (int i = 0; i < a.length; i++) { sum += a[i] * b[i]; } return sum; } static float vectorDot(float[] a, float[] b) { int i = 0; FloatVector acc = FloatVector.zero(SPECIES); int bound = SPECIES.loopBound(a.length); for (; i < bound; i += SPECIES.length()) { acc = FloatVector.fromArray(SPECIES, a, i).fma(FloatVector.fromArray(SPECIES, b, i), acc); } float sum = acc.reduceLanes(VectorOperators.ADD); for (; i < a.length; i++) { // the tail the vector loop could not cover sum += a[i] * b[i]; } return sum; } public static void main(String[] args) { System.out.println("java.version = " + System.getProperty("java.version")); System.out.println("preferred species = " + SPECIES + " (" + SPECIES.length() + " float lanes, machine dependent)"); int n = 1_000_003; // deliberately not a multiple of the lane count float[] a = new float[n], b = new float[n]; for (int i = 0; i < n; i++) { a[i] = (i % 7) * 0.5f; b[i] = (i % 5) * 0.25f; } float scalar = scalarDot(a, b); float vector = vectorDot(a, b); System.out.println("scalar dot = " + scalar); System.out.println("vector dot = " + vector); // Floating-point addition is not associative, so the two sums differ in the last bits; compare with a tolerance. Check.that(Math.abs(scalar - vector) / Math.abs(scalar) < 1e-3, "vector and scalar dot products agree to within 0.1%"); } }