Data-parallel types (SIMD) (since C++26)
Библиотека предоставляет типы с параллельной обработкой данных и операции над этими типами: портативные типы для явного указания параллелизма данных и структурирования данных через ресурсы выполнения с параллельной обработкой данных, где это доступно, такие как SIMD регистры и инструкции или исполнительные блоки, управляемые общим декодером инструкций.
Набор vectorizable types включает:
- все стандартные целочисленные и символьные типы;
- большинство типов с плавающей запятой, включая float , double , и выбранные расширенные типы с плавающей запятой: std:: float16_t , std:: float32_t , и std:: float64_t , если они определены; и
-
std::
complex
<
T
>
где
T- векторный тип с плавающей запятой.
Тип с параллельной обработкой данных состоит из одного или нескольких элементов базового векторизуемого типа, называемого элементным типом . Количество элементов, называемое шириной , является постоянным для каждого типа с параллельной обработкой данных.
Тип с параллельной обработкой данных относится ко всем включенным специализациям шаблонов классов
basic_simd
и
basic_simd_mask
.
Data-parallel объект
типа data-parallel ведет себя аналогично объектам типа
T
. Но в то время как
T
хранит и обрабатывает единственное значение, тип data-parallel с типом элементов
T
хранит и обрабатывает множество значений.
Каждая операция над объектом с параллельной обработкой данных действует поэлементно (за исключением горизонтальных операций, таких как редукции, которые явно обозначены как таковые), применяясь к каждому элементу объекта или к соответствующим элементам двух объектов. Каждое такое применение неупорядочено относительно других. Это простое правило выражает параллелизм данных и будет использоваться компилятором для генерации SIMD инструкций и/или независимых потоков выполнения.
Все операции (за исключением не- constexpr перегрузок математических функций) над объектами data-parallel являются constexpr : возможно создавать и использовать объекты data-parallel при вычислении константных выражений.
Шаблоны псевдонимов
simd
и
simd_mask
определены для того, чтобы позволить пользователям указывать ширину определенного размера. Ширина по умолчанию определяется реализацией во время компиляции.
|
Определено в заголовке
<simd>
|
|
|
Определено в пространстве имён
std::datapar
|
Содержание |
Основные классы
|
(C++26)
|
тип вектора для параллельной обработки данных
(шаблон класса) |
|
(C++26)
|
удобный псевдоним-шаблон для
basic_simd
с возможностью указания ширины
(псевдоним-шаблон) |
|
(C++26)
|
тип для параллельной обработки данных с типом элементов
bool
(шаблон класса) |
|
(C++26)
|
удобный псевдоним-шаблон для
basic_simd_mask
с возможностью указания ширины
(псевдоним-шаблон) |
Флаги загрузки и сохранения
|
(C++26)
|
флаги загрузки и сохранения для типов параллельной обработки данных
(шаблон класса) |
|
(C++26)
|
флаг по умолчанию, используемый в операциях загрузки и сохранения
(константа) |
|
(C++26)
|
флаг, разрешающий преобразования, не сохраняющие значения, в операциях загрузки и сохранения
(константа) |
|
(C++26)
|
флаг, указывающий выравнивание адреса загрузки-сохранения для некоторого заданного хранилища до значения
datapar::alignment
(константа) |
|
(C++26)
|
флаг, указывающий выравнивание адреса загрузки-сохранения для некоторого заданного хранилища до указанного выравнивания
(переменный шаблон) |
Операции загрузки и сохранения
загружает элементы из непрерывного диапазона в
basic_simd
(шаблон функции) |
|
сохраняет элементы из
basic_simd
в непрерывный диапазон
(шаблон функции) |
Приведения типов
|
(C++26)
|
разделяет один объект параллельной обработки данных на несколько
(шаблон функции) |
|
(C++26)
|
объединяет несколько объектов параллельной обработки данных в один
(шаблон функции) |
Алгоритмы
поэлементные операции min/max для
basic_simd
(шаблон функции) |
|
|
(C++26)
|
поэлементная операция clamp для
basic_simd
(шаблон функции) |
|
(C++26)
|
поэлементный выбор с использованием условного оператора
(шаблон функции) |
Редукции
сводит все значения в
basic_simd
к одному значению с помощью указанной бинарной операции
(шаблон функции) |
|
редукции
basic_simd_mask
в
bool
(шаблон функции) |
|
|
(C++26)
|
редукция
basic_simd_mask
в количество
true
значений
(шаблон функции) |
редукции
basic_simd_mask
в индекс первого или последнего
true
значения
(шаблон функции) |
Трейты
|
(C++26)
|
получает соответствующее выравнивание для
datapar::flag_aligned
(шаблон класса) |
|
(C++26)
|
изменяет тип элементов типа данных с параллельной обработкой
(шаблон класса) |
|
(C++26)
|
изменяет ширину типа данных с параллельной обработкой
(шаблон класса) |
Математические функции
Все функции в
<cmath>
и
<complex>
перегружены для
basic_simd
.
|
Этот раздел не завершён
Причина: описание |
Функции для работы с битами
Все функции для манипуляции битами в
<bit>
перегружены для
basic_simd
.
|
Этот раздел не завершён
Причина: описание |
Детали реализации
ABI теги
Типы с параллельной обработкой данных
basic_simd
и
basic_simd_mask
ассоциированы с
тегами ABI
. Эти теги представляют собой типы, которые определяют размер и двоичное представление объектов с параллельной обработкой данных. Конструкция предполагает, что размер и двоичное представление будут варьироваться в зависимости от целевой архитектуры и флагов компилятора. Тег ABI вместе с типом элемента определяет ширину.
Тег ABI остается независимым от выбора набора машинных инструкций. Выбранный набор машинных инструкций ограничивает доступные типы тегов ABI. Теги ABI позволяют пользователям безопасно передавать объекты типа data-parallel через границы единиц трансляции.
| Этот раздел не завершён |
Сущности только для экспозиции
|
Этот раздел не завершён
Причина: требуется обновление |
|
using
/*simd-size-type*/
=
/* см. описание */
;
|
(1) | ( только для демонстрации* ) |
|
template
<
std::
size_t
Bytes
>
using /*integer-from*/ = /* см. описание */ ; |
(2) | ( только для демонстрации* ) |
|
template
<
class
T,
class
Abi
>
constexpr /*simd-size-type*/ /*simd-size-v*/ = /* см. описание */ ; |
(3) | ( только для демонстрации* ) |
|
template
<
class
T
>
constexpr std:: size_t /*mask-element-size*/ = /* см. описание */ ; |
(4) | ( только для демонстрации* ) |
|
template
<
class
T
>
concept /*constexpr-wrapper-like*/ = /* см. описание */ ; |
(5) | ( только для демонстрации* ) |
|
template
<
class
T
>
using /*deduced-simd-t*/ = /* см. описание */ ; |
(6) | ( только для демонстрации* ) |
|
template
<
class
V,
class
T
>
using /*make-compatible-simd-t*/ = /* см. описание */ ; |
(7) | ( только для демонстрации* ) |
T
такого, что
sizeof
(
T
)
равно
Bytes
.
basic_simd<T, Abi>
, или
0
в противном случае.
T
обозначает
std
::
datapar
::
basic_simd_mask
<
Bytes, Abi
>
,
/*mask-element-size*/
<
T
>
равен
Bytes
.
template< class T > concept /*constexpr-wrapper-like*/ = std::convertible_to<T, decltype(T::value)> && std::equality_comparable_with<T, decltype(T::value)> && std::bool_constant<T() == T::value>::value && std::bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;
-
decltype
(
x
+
x
)
, если тип
x
+
x
является активной специализацией
basic_simd; иначе - void .
- /*deduced-simd-t*/ < T > , если этот тип не является void , в противном случае
- std :: datapar :: simd < decltype ( x + x ) , V :: size ( ) > .
|
Требования математических функций
|
||
|
template
<
class
V
>
concept /*simd-floating-point*/ = /* see description */ ; |
(8) | ( только для демонстрации* ) |
|
template
<
class
...
Ts
>
concept /*math-floating-point*/ = /* see description */ ; |
(9) | ( только для демонстрации* ) |
|
template
<
class
...
Ts
>
requires
/*math-floating-point*/
<
Ts...
>
|
(10) | ( только для демонстрации* ) |
|
template
<
class
BinaryOp,
class
T
>
concept /*reduction-binary-operation*/ = /* see description */ ; |
(11) | ( только для демонстрации* ) |
template< class V > concept /*simd-floating-point*/ = std::same_as<V, std::datapar::basic_simd<typename V::value_type, typename V::abi_type>> && std::is_default_constructible_v<V> && std::floating_point<typename V::value_type>;
template< class... Ts > concept /*math-floating-point*/ = (/*simd-floating-point*/</*deduced-simd-t*/<Ts>> || ...);
T0
обозначает
Ts...
[
0
]
,
T1
обозначает
Ts...
[
1
]
, а
TRest
обозначает пакет такой, что
T0, T1, TRest...
эквивалентно
Ts...
. Тогда
/*math-common-simd-t*/
<
Ts...
>
является псевдонимом, эквивалентным:
- /*deduced-simd-t*/ < T0 > , если sizeof... ( Ts ) == 1 равно true
- иначе std:: common_type_t < /*deduced-simd-t*/ < T0 > , /*deduced-simd-t*/ < T1 >> , если sizeof... ( Ts ) == 2 равно true и /*math-floating-point*/ < T0 > && /*math-floating-point*/ < T1 > равно true ,
- иначе std:: common_type_t < /*deduced-simd-t*/ < T0 > , T1 > , если sizeof... ( Ts ) == 2 равно true и /*math-floating-point*/ < T0 > равно true ,
- иначе std:: common_type_t < T0, /*deduced-simd-t*/ < T1 >> , если sizeof... ( Ts ) == 2 равно true ,
- иначе std:: common_type_t < /*math-common-simd-t*/ < T0, T1 > , TRest... > , если /*math-common-simd-t*/ < T0, T1 > является допустимым типом,
- иначе std:: common_type_t < /*math-common-simd-t*/ < TRest... > , T0, T1 > .
template< class BinaryOp, class T > concept /*reduction-binary-operation*/ = requires (const BinaryOp binary_op, const std::datapar::simd<T, 1> v) { { binary_op(v, v) } -> std::same_as<std::datapar::simd<T, 1>>; };
/*reduction-binary-operation*/ < BinaryOp, T > моделируется только если:
-
-
BinaryOpявляется бинарной поэлементной операцией, которая коммутативна, и -
Объект типа
BinaryOpможет быть вызван с двумя аргументами типа std :: datapar :: basic_simd < T, Abi > для неопределенного ABI-тегаAbiи возвращает std :: datapar :: basic_simd < T, Abi > .
-
|
Теги SIMD ABI
|
||
|
template
<
class
T
>
using /*native-abi*/ = /* см. описание */ ; |
(12) | ( только для демонстрации* ) |
|
template
<
class
T,
/*simd-size-type*/
N
>
using /*deduce-abi-t*/ = /* см. описание */ ; |
(13) | ( только для демонстрации* ) |
- /*simd-size-v*/ < T, /*deduce-abi-t*/ < T, N >> равно N ,
- std :: datapar :: basic_simd < T, /*deduce-abi-t*/ < T, N >> является включённой специализацией, и
- std :: datapar :: basic_simd_mask < sizeof ( T ) , /*deduce-abi-t*/ < /*integer-from*/ < sizeof ( T ) > , N >> является включённой специализацией.
T
является векторизуемым типом, и
N
>
0
&&
N
<=
M
равно
true
, где
M
— это определённый реализацией максимум, который составляет не менее
64
и может различаться в зависимости от
T
.
|
Флаги загрузки и сохранения
|
||
|
struct
/*convert-flag*/
;
|
(14) | ( только для демонстрации* ) |
|
struct
/*aligned-flag*/
;
|
(15) | ( только для демонстрации* ) |
|
template
<
std::
size_t
N
>
struct /*overaligned-flag*/ ; |
(16) | ( только для демонстрации* ) |
std::datapar::flags
. Смотрите
флаги загрузки и сохранения
для соответствующих вариантов их использования.
Примечания
| Feature-test макрос | Значение | Стандарт | Функциональность |
|---|---|---|---|
__cpp_lib_simd
|
202411L
|
(C++26) | Типы и операции для параллельной обработки данных |
__cpp_lib_simd_complex
|
202502L
|
(C++26) |
Поддержка чередующихся комплексных значений в
std::datapar::simd
|
Пример
#include <iostream> #include <simd> #include <string_view> void println(std::string_view name, auto const& a) { std::cout << name << ": "; for (std::size_t i{}; i != a.size(); ++i) std::cout << a[i] << ' '; std::cout << '\n'; } template<class A> constexpr std::datapar::basic_simd<int, A> my_abs(std::datapar::basic_simd<int, A> x) { return std::datapar::select(x < 0, -x, x); } int main() { constexpr std::datapar::simd<int> a = 1; println("a", a); constexpr std::datapar::simd<int> b([](int i) { return i - 2; }); println("b", b); constexpr auto c = a + b; println("c", c); constexpr auto d = my_abs(c); println("d", d); constexpr auto e = d * d; println("e", e); constexpr auto inner_product = std::datapar::reduce(e); std::cout << "inner product: " << inner_product << '\n'; constexpr std::datapar::simd<double, 16> x([](int i) { return i; }); println("x", x); // overloaded math functions are defined in <simd> println("cos²(x) + sin²(x)", std::pow(std::cos(x), 2) + std::pow(std::sin(x), 2)); }
Вывод:
a: 1 1 1 1 b: -2 -1 0 1 c: -1 0 1 2 d: 1 0 1 2 e: 1 0 1 4 inner product: 6 x: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cos²(x) + sin²(x): 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Смотрите также
|
числовые массивы, маски массивов и срезы массивов
(шаблон класса) |
Внешние ссылки
| 1. | Реализация раздела 9 "Типы с параллелизмом данных" ISO/IEC TS 19570:2018 — github.com |
| 2. |
Реализация TS доступна для
GCC/libstdc++
(
std::experimental::simd
поставляется с GCC-11) — gcc.gnu.org
|