How to Speed Up Your Vector Operations Using the Java 19 Vector API

Info

This post is part of a blog post series titled 6 New Features in Java 19 That Make Your Life Easier.

Note

This feature is in incubator phase. In order to use it, compile the program with javac --release 19 --enable-preview --add-modules jdk.incubator.vector Main.java and run it with java --enable-preview --add-modules jdk.incubator.vector Main. More details about using incubator modules in your project can be found here.

This API provides classes to express vector computations that, given suitable hardware and runtime ability, are accelerated using vector hardware instructions. When run on a supporting platform, operations can be executed in parallel by the hardware. This style of parallelism is called Single Instruction Multiple Data (SIMD) parallelism. By using the API for vector computations, it should be possible to achieve higher performance than with equivalent scalar computations.

The main goals of the new Vector API are:

  • Provide a clear and concise API
  • The API should be CPU architecture agnostic
  • Compile vector operations to corresponding efficient and performant vector instructions, such as Streaming SIMD Extensions (SSE) and Advanced Vector Extensions (AVX)
  • Provide graceful degradation in situations in which the CPU architecture does not provide special hardware instructions for accelerating vector computations

Below is one example of a scalar computation and another one using the Vector API. We assume that the array arguments are of the same length.

Example of a scalar computation over the elements of an array:

void scalarComputation(float[] a, float[] b, float[] c) {
   for (int i = 0; i < a.length; i++) {
        c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
   }
}

Example using the Vector API:

static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;

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);
    }
}

References

Leave a Comment

Your email address will not be published. Required fields are marked *