Spec-Zone.ru › OpenJDK 17

Пакет jdk.incubator.vector

package jdk.incubator.vector

Экспериментальная функция. Будет удалена в будущей версии.

Этот пакет предоставляет классы для выражения векторных вычислений, которые, при наличии подходящего оборудования и возможностей среды выполнения, ускоряются с помощью векторных инструкций аппаратного обеспечения.

Вектор представляет собой последовательность фиксированного числа элементов, все из одного фиксированного типа элемента, например, byte, long, или float. Каждый элемент содержит независимое значение типа элемента. Операции над векторами обычно являются элементными, распределяя некоторый скалярный оператор (например, сложение) по элементам участвующих векторов, обычно генерируя векторный результат, элементы которого содержат различные скалярные результаты. При выполнении на поддерживающей платформе элементные операции могут выполняться параллельно аппаратным обеспечением. Этот стиль параллелизма называется параллелизмом Single Instruction Multiple Data (SIMD).

В стиле программирования SIMD большинство операций внутри элемента являются безусловными, но эффект условного выполнения может быть достигнут с помощью маскированных операций, таких как blend(), под управлением связанной VectorMask. Перемещение данных, отличное от строгого потока по элементам, достигается с помощью межэлементных операций, часто под управлением связанного VectorShuffle. Данные элементов и/или целые векторы могут быть переформатированы с помощью различных типов элементных преобразований и байтовых переформатирований переинтерпретаций, часто под управлением рефлексивного объекта VectorSpecies, который выбирает альтернативный формат вектора, отличный от входного вектора.

Vector<E> объявляет набор векторных операций (методов), общих для всех типов элементов. Эти общие операции включают общий доступ к значениям элементов, выбор и перемещение данных, переформатирование и определённые арифметические и логические операции (такие как сложение или сравнение), общие для всех примитивных типов.

Открытые подтипы Vector соответствуют конкретным типам элементов. Они объявляют дополнительные операции, специфичные для данного типа элемента, включая неявный доступ к значениям элементов, побитовые операции над значениями целочисленных типов элементов или трансцендентные операции над значениями типов с плавающей запятой.

Некоторые элементные операции, такие как оператор add, определены как полная именованная операция, где соответствующий метод в Vector предоставляется в маскированных и не-маскированных перегрузках, а также (в подтипах) в ковариативных перегрузках (возвращающих подтип) и дополнительных перегрузках с скалярным разнесением (как маскированные, так и не-маскированные). Другие элементные операции, такие как оператор min, определены как частично обслуживаемая (не полная) именованная операция, где соответствующий метод в Vector и/или подтипе предоставляют некоторые, но не все возможные перегрузки и переопределения (обычно не-маскированную версию со скалярным разнесением). Наконец, все элементные операции (те, что названы, как описано ранее, или те, что представлены в виде методов) имеют соответствующий operator token, объявленный как статическая константа в VectorOperators. Каждый оператор определяет символическое Java-выражение для операции, например, a + b для оператора ADD. Универсальные методы, принимающие токены элементных операций, такие как для элементной операции, предоставляются в Vector и предлагаются в тех же вариантах, что и полная именованная операция.

Этот пакет содержит общедоступный подтип Vector, соответствующий каждому поддерживаемому типу элемента: ByteVector, ShortVector, IntVector, LongVector, FloatVector и DoubleVector.

Вот пример умножения элементов двух массивов с плавающей точкой a и b с использованием векторных вычислений и сохранение результата в массиве c.


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

 void vectorMultiply(float[] a, float[] b, float[] c) {
   // It is assumed array arguments are of the same size
   for (int i = 0; i < a.length; i += SPECIES.length()) {
         VectorMask<Float> m = SPECIES.indexInRange(i, a.length);
         FloatVector va = FloatVector.fromArray(SPECIES, a, i, m);
         FloatVector vb = FloatVector.fromArray(SPECIES, b, i, m);
         FloatVector vc = va.mul(vb)
         vc.intoArray(c, i, m);
   }
 }
 
В приведенном выше примере мы используем маски, сгенерированные с помощью indexInRange(), чтобы предотвратить чтение/запись за пределами длины массива. Первые a.length / SPECIES.length() итерации будут иметь маску со всеми элементами, установленными. Только в последней итерации (если a.length не кратно SPECIES.length() ) будет иметь маску с установленными первыми a.length % SPECIES.length() элементами. Поскольку маска используется во всех итерациях, данное решение может не обеспечить оптимальную производительность (для больших длин массивов). То же самое вычисление можно реализовать без масок следующим образом:

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

 void vectorMultiply(float[] a, float[] b, float[] c) {
   int i = 0;
   // It is assumed array arguments are of the same size
   for (; i < SPECIES.loopBound(a.length); i += SPECIES.length()) {
         FloatVector va = FloatVector.fromArray(SPECIES, a, i);
         FloatVector vb = FloatVector.fromArray(SPECIES, b, i);
         FloatVector vc = va.mul(vb)
         vc.intoArray(c, i);
   }

   for (; i < a.length; i++) {
     c[i] = a[i] * b[i];
   }
 }
 
Скалярные вычисления после векторных вычислений необходимы для обработки хвоста элементов массива TLENGTH, где TLENGTH < SPECIES.length() для векторного вида. Приведенные выше примеры используют предпочтительный вид (FloatVector.SPECIES_PREFERRED), гарантируя, что код динамически адаптируется к оптимальной форме для платформы, на которой он выполняется.

В приведенном коде используется вспомогательный метод loopBound() для определения конца векторного цикла. Здесь также может быть использовано примитивное выражение маски, такое как (a.length & ~(SPECIES.length() - 1)), так как SPECIES.length() известно как 8, которое является степенью двойки. Но это не всегда верное предположение. Например, если FloatVector.SPECIES_PREFERRED имеет платформозависимую форму S_Max_BIT, и эта форма имеет некоторую странную гипотетическую величину, такую как 384 (что является допустимым размером вектора согласно некоторым архитектурам), то примитивное выражение маски может привести к неожиданным результатам.

Примечания по производительности

Этот пакет зависит от способности среды выполнения динамически компилировать векторные операции в оптимальные инструкции векторного аппаратного обеспечения. Существует стандартная скалярная реализация для каждой операции, которая используется, если операция не может быть скомпилирована в векторные инструкции.

Есть некоторые моменты, на которые пользователи должны обратить внимание для получения оптимального кода векторной машины:

  • Форма используемых векторов должна поддерживаться базовой платформой. Например, код, написанный с использованием IntVector вида VectorShape S_512_BIT не будет скомпилирован в векторные инструкции на платформе, которая поддерживает только векторы длиной 256 бит. Вместо этого будет использована стандартная скалярная реализация. По этой причине рекомендуется использовать предпочтительный вид, как показано выше, для написания векторных вычислений с переменным размером.
  • Большинство классов, определённых в этом пакете, должны рассматриваться как классы значений. Эта классификация относится к Vector и его подтипам, VectorMask, VectorShuffle и VectorSpecies. С этими типами операции, чувствительные к идентичности, такие как == могут привести к непредсказуемым результатам или снижению производительности. Удивительно, но v.equals(w) может оказаться быстрее, чем v==w, так как equals не является чувствительной к идентичности. Также эти объекты могут храниться в локальных переменных и параметрах, а также как static final константы, но хранение их в других полях Java или элементах массивов, хотя и семантически допустимо, может привести к снижению производительности.

Для каждого класса в этом пакете, если не указано иное, все аргументы метода ссылочного типа не должны быть null, а любой null-аргумент вызовет NullPointerException. Этот факт не документируется индивидуально для методов данной API.

Класс Описание
ByteVector
Специализированный Vector, представляющий упорядоченную неизменяемую последовательность byte значений.
DoubleVector
Специализированный Vector, представляющий упорядоченную неизменяемую последовательность double значений.
FloatVector
Специализированный Vector, представляющий упорядоченную неизменяемую последовательность float значений.
IntVector
Специализированный Vector, представляющий упорядоченную неизменяемую последовательность int значений.
LongVector
Специализированный Vector, представляющий упорядоченную неизменяемую последовательность long значений.
ShortVector
Специализированный Vector, представляющий упорядоченную неизменяемую последовательность short значений.
Vector<E>
Последовательность фиксированного числа ланей, все из которых имеют фиксированный тип элемента, например byte, long, или float.
VectorMask<E>
VectorMask представляет упорядоченную неизменяемую последовательность boolean значений.
VectorOperators
Этот класс состоит только из статических констант, описывающих операции над векторами по ланям, плюс вложенные интерфейсы, которые их классифицируют.
VectorOperators.Associative
Тип для всех ассоциативных операций по ланям бинарных операторов, используемых в выражениях, таких как e = v0.reduceLanes(ADD).
VectorOperators.Binary
Тип для всех операций по ланям бинарных (двух аргументных) операторов, используемых в выражениях, таких как w = v0.lanewise(ADD, v1).
VectorOperators.Comparison
Тип для всех бинарных операций по ланям логических сравнений значений ланей, используемых в выражениях, таких как m = v0.compare(LT, v1).
VectorOperators.Conversion<E,F>
Тип для всех операций по ланям преобразований значений ланей, используемых в выражениях, таких как w1 = v0.convert(I2D, 1).
VectorOperators.Operator
Основной тип для всех операторных маркеров, предоставляющий запросы для общих свойств, таких как арность, типы аргументов и возвращаемых значений, символьное имя и имя оператора.
VectorOperators.Ternary
Тип для всех операций по ланям тернарных (трех аргументных) операторов, используемых в выражениях, таких как w = v0.lanewise(FMA, v1, v2).
VectorOperators.Test
Тип для всех унарных операций по ланям логических тестов значений ланей, используемых в выражениях, таких как m = v0.test(IS_FINITE).
VectorOperators.Unary
Тип для всех операций по ланям унарных (одноаргументных) операторов, используемых в выражениях, таких как w = v0.lanewise(NEG).
VectorShape
VectorShape выбирает определенную реализацию Vector.
VectorShuffle<E>
VectorShuffle представляет упорядоченную неизменяемую последовательность int значений, называемых индексами источника, где каждый индекс источника численно выбирает исходную лань из совместимого Vector.
VectorSpecies<E>
Интерфейс для управления всеми векторами с одинаковой комбинацией типа элемента (ETYPE) и shape.

© 1993, 2021, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/17/docs/api/jdk.incubator.vector/jdk/incubator/vector/package-summary.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API