

Looking into the JDK 16 vector API
source link: https://www.mscharhag.com/java/vector-api
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

JDK 16 comes with the incubator module jdk.incubator.vector (JEP 338) which provides a portable API for expressing vector computations. In this post we will have a quick look at this new API.
Note that the API is in incubator status and likely to change in future releases.
Why vector operations?
When supported by the underlying hardware vector operations can increase the number of computations performed in a single CPU cycle.
Assume we want to add two vectors each containing a sequence of four integer values. Vector hardware allows us to perform this operation (four integer additions in total) in a single CPU cycle. Ordinary additions would only perform one integer addition in the same time.
The new vector API allows us to define vector operations in a platform agnostic way. These operations then compile to vector hardware instructions at runtime.
Note that HotSpot already supports auto-vectorization which can transform scalar operations into vector hardware instructions. However, this approach is quite limited and utilizes only a small set of available vector hardware instructions.
A few example domains that might benefit from the new vector API are machine learning, linear algebra or cryptography.
Enabling the vector incubator module (jdk.incubator.vector)
To use the new vector API we need to use JDK 16 (or newer). We also need to add the jdk.incubator.vector module to our project. This can be done with a module-info.java file:
module com.mscharhag.vectorapi {
requires jdk.incubator.vector;
}
Implementing a simple vector operation
Let's start with a simple example:
float
[] a =
new
float
[] {1f, 2f, 3f, 4f};
float
[] b =
new
float
[] {5f, 8f, 10f, 12f};
FloatVector first = FloatVector.fromArray(FloatVector.SPECIES_128, a,
0
);
FloatVector second = FloatVector.fromArray(FloatVector.SPECIES_128, b,
0
);
FloatVector result = first
.add(second)
.pow(
2
)
.neg();
We start with two float arrays (a and b) each containing four elements. These provide the input data for our vectors.
Next we create two FloatVectors using the static fromArray(..) factory method. The first parameter defines the size of the vector in bits (here 128). Using the last parameter we are able to define an offset value for the passed arrays (here we use 0)
In Java a float value has a size of four bytes (= 32 bits). So, four float values match exactly the size of our vector (128 bits).
After that, we can define our vector operations. In this example we add both vectors together, then we square and negate the result.
The resulting vector contains the values:
[-36.0, -100.0, -169.0, -256.0]
We can write the resulting vector into an array using the intoArray(..) method:
float
[] resultArray =
new
float
[
4
];
result.intoArray(resultArray,
0
);
In this example we use FloatVector to define operations on float values. Of course we can use other numeric types too. Vector classes are available for byte, short, integer, float and double (ByteVector, ShortVector, etc.).
Working with loops
While the previous example was simple to understand it does not show a typical use case of the new vector API. To gain any benefits from vector operations we usually need to process larger amounts of data.
In the following example we start with three arrays a, b and c, each having 10000 elements. We want to add the values of a and b and store it in c: c[i] = a[i] + b[i].
Our code looks like this:
final
VectorSpecies<Float> SPECIES = FloatVector.SPECIES_128;
float
[] a = randomFloatArray(10_000);
float
[] b = randomFloatArray(10_000);
float
[] c =
new
float
[10_000];
for
(
int
i =
0
; i < a.length; i += SPECIES.length()) {
VectorMask<Float> mask = SPECIES.indexInRange(i, a.length);
FloatVector first = FloatVector.fromArray(SPECIES, a, i, mask);
FloatVector second = FloatVector.fromArray(SPECIES, b, i, mask);
first.add(second).intoArray(c, i, mask);
}
Here we iterate over the input arrays in strides of vector length. A VectorMask helps us if vectors cannot be completely filled from input data (e.g. during the last loop iteration).
Summary
We can use the new vector API to define vector operations for optimizing computations for vector hardware. This way we can increase the number of computations performed in a single CPU cycle. Central element of the vector API are type specific vector classes like FloatVector or LongVector.
You can find the example source code on GitHub.
Recommend
-
85
-
2
Looking into the futureThis website uses cookiesWe use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our so...
-
17
Hands-on: Looking Glass Portrait is a window into the holographic data era Image Credit: Jeremy Horwitz/VentureBeat ADVERTISEMENT Ever since R2-D2 proje...
-
5
This new Progressive Web App can turn images into SVG vector graphicsThere are two different categories of images you typically see on the web. Raster images (like JPG, PNG, WebP, and so on) are a series of pixels at a fixed res...
-
7
Java16的Vector API更好支持机器学习 Vector API 提供了一种用 Java 编写跨平台数据并行算法的机制,例如复杂的数学和基于数组的运算。Vector API 提供了一个可移植的 API 来表达向量数学计算。API 的第一次迭代由
-
5
Java 18:Vector API自动加速 解道Jdon ...
-
7
OwnerPaul SandozTypeFeatureScopeJDKStatusProposed to TargetRelease20Componentcore-li...
-
3
Java Vector API on AArch64
-
5
JDK外部函数Panama API性能超过了JNI Java 本地调用 API 的 JMH 性能基准:
-
3
Repository files navigation🦉AthenaDB⚡️ Serverless, distributed Vector Database as an API written with Cloudflare Workers, Workers AI, D1, and Vectorize. AthenaDB is a simple, serverless, distribu...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK