Package jdk.incubator.vector
Incubating Feature. Will be removed in a future release.
Classes to express vector computations that, given suitable hardware and runtime ability, are accelerated using vector hardware instructions.
Vector computations consist of a sequence of operations on vectors. A vector is a fixed sequence of scalar values; a scalar value is a single unit of value such as an int, a long, a float and so on. Operations on vectors typically perform the equivalent scalar operation on all scalar values of the participating vectors, usually generating a vector result. When run on a supporting platform, these operations can be executed in parallel by the hardware. This style of parallelism is called Single Instruction Multiple Data (SIMD) parallelism.
The abstract class Vector
represents an ordered immutable sequence of
values of the same element type 'e' that is one of the following primitive types -
byte, short, int, long, float, or double. The type variable E corresponds to the
boxed element type, specifically the class that wraps a value of e in an object
(such as Integer class that wraps a value of int).
Vector declares a set of vector operations (methods) that are common to
all element types (such as addition). Subclasses of Vector corresponding to
a specific element type declare further operations that are specific to that element type
(such as access to element values in lanes, logical operations on values of integral
elements types, or transcendental operations on values of floating point element
types). There are six abstract subclasses of Vector
corresponding to the supported set of
element types: ByteVector
, ShortVector
,
IntVector
, LongVector
,
FloatVector
, and DoubleVector
.
In addition to element type, vectors are parameterized by their shape,
which is their length. The supported shapes are
represented by the enum jdk.incubator.vector.Vector.Shape
.
The combination of element type and shape determines a vector species,
represented by jdk.incubator.vector.Vector.Species
. The various typed
vector classes expose static constants corresponding to the supported species,
and static methods on these types generally take a species as a parameter.
For example,
FloatVector.fromArray()
creates and returns a float vector of the specified species, with elements
loaded from the specified float array.
The species instance for a specific combination of element type and shape can be obtained by reading the appropriate static field, as follows:
{@code Vector.Species
Code that is agnostic to species can request the "preferred" species for a
given element type, where the optimal size is selected for the current platform:
{@code Vector.Species
Here is an example of multiplying elements of two float arrays {@code a and b} using vector computation
and storing result in array {@code c}.
If a vector operation does not belong to one of the above categories then
the operation explicitly specifies how it processes the lane elements of
input vectors, and where appropriate expresses the behavior using
pseudocode.
Many vector operations provide an additional {@link jdk.incubator.vector.Vector.Mask mask}-accepting
variant.
The mask controls which lanes are selected for application of the scalar
operation. Masks are a key component for the support of control flow in
vector computations.
For certain operation categories the mask accepting variants can be specified
in generic terms. If a lane of the mask is set then the scalar operation is
applied to corresponding lane elements, otherwise if a lane of a mask is not
set then a default scalar operation is applied and its result is placed into
the vector result at the same lane. The default operation is specified for
the following operation categories:
For convenience, many vector operations of arity greater than one provide
an additional scalar-accepting variant (such as adding a constant scalar
value to all lanes of a vector). This variant accepts compatible
scalar values instead of vectors for the second and subsequent input vectors,
if any.
Unless otherwise specified the scalar variant behaves as if each scalar value
is transformed to a vector using the appropriate vector {@code broadcast} operation, and
then the vector accepting vector operation is applied using the transformed
values.
There are certain things users need to pay attention to for generating optimal vector machine code:
{@code
static final Vector.Species
The scalar computation after the vector computation is required to process the tail of
elements, the length of which is smaller than the species length.
The example above uses vectors hardcoded to a concrete shape (512-bit). Instead, we could use preferred
species as shown below, to make the code dynamically adapt to optimal shape for the platform on which it runs.
{@code
static final Vector.Species
Vector operations
We use the term lanes when defining operations on vectors. The number of lanes
in a vector is the number of scalar elements it holds. For example, a vector of
type {@code Float} and shape {@code Shape.S_256_BIT} has eight lanes.
Vector operations can be grouped into various categories and their behavior
generally specified as follows:
Some vector operations are specified as instance methods (such as adding
one vector to another); others are specified as static methods (such as
loading vector values from an array.)
{@code
EVector a = ...;
e[] ar = new e[a.length()];
for (int i = 0; i < a.length(); i++) {
ar[i] = scalar_unary_op(a.get(i));
}
EVector r = EVector.fromArray(a.species(), ar, 0);
}
Unless otherwise specified the input and result vectors will have the same
element type and shape.
{@code
EVector a = ...;
EVector b = ...;
e[] ar = new e[a.length()];
for (int i = 0; i < a.length(); i++) {
ar[i] = scalar_binary_op(a.get(i), b.get(i));
}
EVector r = EVector.fromArray(a.species(), ar, 0);
}
Unless otherwise specified the two input and result vectors will have the
same element type and shape.
{@code
EVector a = ...;
e r =
Unless otherwise specified the scalar result type and element type will be
the same.
{@code
EVector a = ...;
EVector b = ...;
boolean[] ar = new boolean[a.length()];
for (int i = 0; i < a.length(); i++) {
ar[i] = scalar_binary_test_op(a.get(i), b.get(i));
}
Mask
Unless otherwise specified the two input vectors and result mask will have
the same element type and shape.
Otherwise, the mask accepting variant of the operation explicitly specifies
how it processes the lane elements of input vectors, and where appropriate
expresses the behavior using pseudocode.
Performance notes
This package depends on the runtime's ability to dynamically compile vector operations
into optimal vector hardware instructions. There is a default scalar implementation
for each operation which is used if the operation cannot be compiled to vector instructions.
-
Class Summary Class Description ByteVector A specializedVector
representing an ordered immutable sequence ofbyte
values.DoubleVector A specializedVector
representing an ordered immutable sequence ofdouble
values.FloatVector A specializedVector
representing an ordered immutable sequence offloat
values.IntVector A specializedVector
representing an ordered immutable sequence ofint
values.LongVector A specializedVector
representing an ordered immutable sequence oflong
values.Mask<E> AMask
represents an ordered immutable sequence ofboolean
values.ShortVector A specializedVector
representing an ordered immutable sequence ofshort
values.Shuffle<E> AShuffle
represents an ordered immutable sequence ofint
values.Species<E> Class representing vectors of same element type,E
andShape
.Vector<E> AVector
is designed for use in computations that can be transformed by a runtime compiler, on supported hardware, to Single Instruction Multiple Data (SIMD) computations leveraging vector hardware registers and vector hardware instructions.