Spec-Zone.ru › C++

Типы с параллелизмом по данным (SIMD) (начиная с C++26)

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

Множество векторизуемых типов включает:

  • все стандартные целочисленные типы и символьные типы;
  • большинство типов с плавающей точкой, включая float, double и выбранные расширенные типы с плавающей точкой: std::float16_t, std::float32_t и std::float64_t, если они определены; и
  • std::complex<T>, где T — векторизуемый тип с плавающей точкой.

Тип с параллелизмом по данным состоит из одного или нескольких элементов базового векторизуемого типа, называемого типом элемента . Количество элементов, называемое шириной , является постоянным для каждого типа с параллелизмом по данным.

Тип с параллелизмом по данным обозначает все разрешённые специализации шаблонов классов basic_vec и basic_mask.

Объект с параллелизмом по данным типа с параллелизмом по данным ведёт себя аналогично объектам типа T. Однако, если T хранит и обрабатывает одно значение, тип с параллелизмом по данным и типом элемента T хранит и обрабатывает несколько значений.

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

Все операции (кроме перегрузок математических функций, не являющихся constexpr) над объектами с параллелизмом по данным являются constexpr: можно создавать и использовать такие объекты при вычислении константного выражения.

Шаблоны псевдонимов vec и mask определены, чтобы позволить пользователям задавать ширину определённого размера. Ширина по умолчанию определяется реализацией во время компиляции.

Определено в заголовке <simd>
Определено в пространстве имён std::simd

Основные классы

simd::basic_vec
(C++26)
векторный тип с параллелизмом по данным
(шаблон класса)
simd::vec
(C++26)
удобный шаблон псевдонима для basic_vec, позволяющий задавать его ширину
(шаблон псевдонима)
simd::basic_mask
(C++26)
тип с параллелизмом по данным и типом элемента bool
(шаблон класса)
simd::mask
(C++26)
удобный шаблон псевдонима для basic_mask, позволяющий задавать его ширину
(шаблон псевдонима)

Флаги загрузки и сохранения

simd::flags
(C++26)
флаги загрузки и сохранения для типов с параллелизмом по данным
(шаблон класса)
simd::flag_default
(C++26)
флаг по умолчанию, используемый в операциях загрузки и сохранения
(константа)
simd::flag_convert
(C++26)
флаг, разрешающий преобразования, не сохраняющие значение, в операциях загрузки и сохранения
(константа)
simd::flag_aligned
(C++26)
флаг, указывающий, что адрес загрузки-сохранения выровнен относительно некоторой заданной области хранения до значения simd::alignment
(константа)
simd::flag_overaligned
(C++26)
флаг, указывающий, что адрес загрузки-сохранения выровнен относительно некоторой заданной области хранения до указанного значения выравнивания
(шаблон переменной)

Операции загрузки и сохранения

simd::unchecked_loadsimd::partial_load
(C++26)
загружает элементы из непрерывного диапазона в basic_vec
(шаблон функции)
simd::unchecked_storesimd::partial_store
(C++26)
сохраняет элементы из basic_vec в непрерывный диапазон
(шаблон функции)

Преобразования типов

simd::chunk
(C++26)
разбивает один объект с параллелизмом по данным на несколько объектов
(шаблон функции)
simd::cat
(C++26)
объединяет несколько объектов с параллелизмом по данным в один объект
(шаблон функции)

Алгоритмы

simd::minsimd::maxsimd::minmax
(C++26)
поэлементные операции нахождения минимума/максимума для basic_vec
(шаблон функции)
simd::clamp
(C++26)
поэлементная операция ограничения значения диапазоном для basic_vec
(шаблон функции)
simd::select
(C++26)
поэлементный выбор с использованием условного оператора
(шаблон функции)

Редукции

simd::reducesimd::reduce_minsimd::reduce_max
(C++26)
сводит все значения в basic_vec к одному значению с помощью заданной бинарной операции
(шаблон функции)
simd::all_ofsimd::any_ofsimd::none_of
(C++26)
редукции basic_mask к типу bool
(шаблон функции)
simd::reduce_count
(C++26)
редукция basic_mask к количеству значений true
(шаблон функции)
simd::reduce_min_indexsimd::reduce_max_index
(C++26)
редукции basic_mask к индексу первого или последнего значения true
(шаблон функции)

Перестановки

simd::zero_elementsimd::uninit_element
(C++26)
специальные значения для статического permute
(константа)
simd::permute
(C++26)
статические и динамические перестановки basic_vec и basic_mask
(шаблон функции)
simd::compresssimd::expand
(C++26)
перестановки со сжатием/расширением basic_vec и basic_mask в соответствии с заданной basic_mask
(шаблон функции)
simd::unchecked_gather_fromsimd::partial_gather_fromsimd::unchecked_scatter_tosimd::partial_scatter_to
(C++26)
перестановки basic_vec из/в память с необязательной маской записи
(шаблон функции)

Свойства типов

simd::alignment
(C++26)
получает подходящее выравнивание для simd::flag_aligned
(шаблон класса)
simd::rebind
(C++26)
изменяет тип элемента типа с параллелизмом по данным
(шаблон класса)
simd::resize
(C++26)
изменяет ширину типа с параллелизмом по данным
(шаблон класса)

Математические функции

Все функции из <cmath> и <complex> перегружены для basic_vec.

Функции манипуляции битами

Все функции манипуляции битами из <bit>, кроме std::bit_cast, перегружены для basic_vec.

Подробности реализации

Теги ABI

Типы с параллелизмом по данным basic_vec и basic_mask связаны с тегами ABI . Эти теги — типы, задающие размер и двоичное представление объектов с параллелизмом по данным. Предполагается, что размер и двоичное представление будут изменяться в зависимости от целевой архитектуры и флагов компилятора. Тег ABI вместе с типом элемента определяет ширину.

Тег ABI не зависит от выбора набора машинных инструкций. Выбранный набор машинных инструкций ограничивает используемые типы тегов ABI. Теги ABI позволяют пользователям безопасно передавать объекты типа с параллелизмом по данным через границы единиц трансляции.

Сущности, используемые только для описания

using /*simd-size-type*/ = /* see description */;
(1) (только для описания*)
template< std::size_t Bytes >
using /*integer-from*/ = /* see description */;
(2) (только для описания*)
template< class T, class Abi >
constexpr /*simd-size-type*/ /*simd-size-v*/ = /* see description */;
(3) (только для описания*)
template< class T >
constexpr std::size_t /*mask-element-size*/ = /* see description */;
(4) (только для описания*)
template< class T >
concept /*constexpr-wrapper-like*/ = /* see description */;
(5) (только для описания*)
template< class T >
using /*deduced-simd-t*/ = /* see description */;
(6) (только для описания*)
template< class V, class T >
using /*make-compatible-simd-t*/ = /* see description */;
(7) (только для описания*)
1) /*simd-size-type*/ — псевдоним знакового целочисленного типа. Реализация может выбрать любой знаковый целочисленный тип.
2) /*integer-from*/<Bytes> — псевдоним знакового целочисленного типа T, такого что sizeof(T) равно Bytes.
3) /*simd-size-v*/<T,Abi> обозначает ширину разрешённой специализации basic_vec<T, Abi> или 0 в противном случае.
4) Если T обозначает std::simd::basic_mask<Bytes,Abi>, то /*mask-element-size*/<T> равно Bytes.
5) Концепт /*constexpr-wrapper-like*/ определён следующим образом:
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;
6) Пусть x — lvalue типа constT. /*deduced-simd-t*/<T> — псевдоним, эквивалентный:
  • decltype(x+x), если тип x + x является разрешённой специализацией basic_vec; в противном случае
  • void.
7) Пусть x — lvalue типа constT. /*make-compatible-simd-t*/<V,T> — псевдоним, эквивалентный:
  • /*deduced-simd-t*/<T>, если этот тип не равен void; в противном случае
  • std::simd::vec<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...>
using /*math-common-simd-t*/ = /* see description */;
(10) (только для описания*)
template< class BinaryOp, class T >
concept /*reduction-binary-operation*/ = /* see description */;
(11) (только для описания*)
8) Концепт /*simd-floating-point*/ определён следующим образом:
template< class V >
concept /*simd-floating-point*/ =
    std::same_as<V,
                 std::simd::basic_vec<typename V::value_type,
                 typename V::abi_type>> &&
    std::is_default_constructible_v<V> && 
    std::floating_point<typename V::value_type>;
9) Концепт /*math-floating-point*/ определён следующим образом:
template< class... Ts >
concept /*math-floating-point*/ =
    (/*simd-floating-point*/</*deduced-simd-t*/<Ts>> || ...);
10) Пусть 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>.
11) Концепт /*reduction-binary-operation*/ определён следующим образом:
template< class BinaryOp, class T >
concept /*reduction-binary-operation*/ =
    requires (const BinaryOp binary_op, const std::simd::vec<T, 1> v) {
        { binary_op(v, v) } -> std::same_as<std::simd::vec<T, 1>>;
    };

/*reduction-binary-operation*/<BinaryOp,T> моделируется только если:

  • BinaryOp является коммутативной поэлементной бинарной операцией, и
  • объект типа BinaryOp можно вызвать с двумя аргументами типа std::simd::basic_vec<T,Abi> для неуказанного тега ABI Abi; вызов возвращает std::simd::basic_vec<T,Abi>.
Теги ABI SIMD
template< class T >
using /*native-abi*/ = /* see description */;
(12) (только для экспозиции*)
template< class T, /*simd-size-type*/ N >
using /*deduce-abi-t*/ = /* see description */;
(13) (только для экспозиции*)
12) /*native-abi*/<T> — псевдоним для тега ABI, определяемый реализацией. Это основной тег ABI, который следует использовать для эффективной явной векторизации. В результате basic_vec<T,/*native-abi*/<T>> является разрешённой специализацией.
13)/*deduce-abi-t*/<T,N> — псевдоним, обозначающий тип тега ABI, такой что:
  • /*simd-size-v*/<T,/*deduce-abi-t*/<T,N>> равен N,
  • std::simd::basic_vec<T,/*deduce-abi-t*/<T,N>> является разрешённой специализацией, и
  • std::simd::basic_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) (только для экспозиции*)
14-16) Эти типы тегов используются в качестве аргумента шаблона для std::simd::flags. Соответствующие варианты использования описаны в разделе флаги загрузки и сохранения.

Примечания

Макрос проверки поддержки Значение Стандарт Возможность
__cpp_lib_simd 202411L (C++26) Типы и операции для обработки данных в параллельном режиме
202603L (C++26) Преобразование consteval с сохранением значения в simd::vec
__cpp_lib_simd_complex 202502L (C++26) Чередующиеся комплексные значения
__cpp_lib_simd_permutations 202506L (C++26) Перестановки SIMD

Пример

#include <iostream>
#include <simd>
#include <string_view>

namespace simd = std::simd;

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 simd::basic_vec<int, A> my_abs(simd::basic_vec<int, A> x)
{
    return simd::select(x < 0, -x, x);
}

int main()
{
    constexpr simd::vec<int> a = 1;
    println("a", a);

    constexpr simd::vec<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 = simd::reduce(e);
    std::cout << "inner product: " << inner_product << '\n';

    constexpr simd::vec<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

См. также

simd
(parallelism TS v2)
тип вектора для обработки данных в параллельном режиме
(шаблон класса)
valarray
числовые массивы, маски массивов и срезы массивов
(шаблон класса)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/numeric/simd

Spec-Zone.ru

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