命名空间
变体
操作

数据并行类型 (SIMD) (C++26 起)

来自 cppreference.cn
< cpp‎ | numeric
 
 
 
 

该库提供了数据并行类型和对这些类型的操作:用于明确声明数据并行性并通过数据并行执行资源(如 SIMD 寄存器和指令或由通用指令解码器驱动的执行单元)构造数据的可移植类型。

所有标准整数类型、字符类型和大多数浮点类型都是可矢量化类型。可矢量化浮点类型包括 floatdouble,以及如果定义了的话,选定的扩展浮点类型 std::float16_tstd::float32_tstd::float64_t

一个数据并行类型由一个或多个底层可矢量化类型(称为元素类型)的元素组成。元素的数量(称为宽度)对于每个数据并行类型都是恒定的。

数据并行类型指的是类模板 basic_simdbasic_simd_mask 的所有已启用特化。

数据并行类型的一个数据并行对象的行为类似于 T 类型的对象。但是,虽然 T 存储和操作单个值,但元素类型为 T 的数据并行类型存储和操作多个值。

对数据并行对象的每个操作都是元素级的(除了水平操作,例如归约,这些操作明确地标记为水平操作),应用于对象的每个元素或两个对象的相应元素。每个这样的应用与其他应用之间没有顺序。这个简单的规则表达了数据并行性,并将由编译器用于生成 SIMD 指令和/或独立的执行流。

对数据并行对象的所有操作(非 constexpr 数学函数重载除外)都是 constexpr:可以在常量表达式的求值中创建和使用数据并行对象。

别名模板 simdsimd_mask 被定义为允许用户将宽度指定为某个大小。默认宽度由实现在编译时确定。

定义于头文件 <simd>

目录

[编辑] 主要类

数据并行向量类型
(类模板) [编辑]
(C++26)
basic_simd 的便捷别名模板,可以指定其宽度
(别名模板)[编辑]
元素类型为 bool 的数据并行类型
(类模板) [编辑]
(C++26)
basic_simd_mask 的便捷别名模板,可以指定其宽度
(别名模板)[编辑]

[编辑] 加载和存储标志

数据并行类型的加载和存储标志
(类模板) [编辑]
加载和存储操作中使用的默认标志
(常量) [编辑]
在加载和存储操作中启用非值保留转换的标志
(常量) [编辑]
标志,指示加载-存储地址与指定存储的 simd_alignment 值对齐
(常量) [编辑]
标志,指示加载-存储地址与指定存储的指定对齐方式对齐
(变量模板)[编辑]

[编辑] 加载和存储操作

从连续范围加载元素到 basic_simd
(函数模板) [编辑]
basic_simd 存储元素到连续范围
(函数模板) [编辑]

[编辑] 转换

将单个数据并行对象拆分为多个
(函数模板) [编辑]
(C++26)
将多个数据并行对象连接成一个
(函数模板) [编辑]

[编辑] 算法

basic_simd 的元素级 min/max 操作
(函数模板) [编辑]
(C++26)
basic_simd 的元素级 clamp 操作
(函数模板) [编辑]
使用条件运算符进行元素级选择
(函数模板) [编辑]

[编辑] 归约

basic_simd 中的所有值通过指定的二元操作归约到单个值
(函数模板) [编辑]
basic_simd_mask 归约到 bool
(函数模板) [编辑]
basic_simd_mask 归约到 true 值的数量
(函数模板) [编辑]
basic_simd_mask 归约到第一个或最后一个 true 值的索引
(函数模板) [编辑]

[编辑] 特性

获取 simd_flag_aligned 的适当对齐方式
(类模板) [编辑]
更改数据并行类型的元素类型
(类模板) [编辑]
更改数据并行类型的宽度
(类模板) [编辑]

[编辑] 数学函数

<cmath> 中的所有函数都为 basic_simd 重载。

[编辑] 实现细节

[编辑] ABI 标签

数据并行类型 basic_simdbasic_simd_maskABI 标签关联。这些标签是指定数据并行对象大小和二进制表示的类型。该设计旨在使大小和二进制表示根据目标架构和编译器标志而变化。ABI 标签与元素类型一起确定宽度。

ABI 标签独立于机器指令集选择。所选的机器指令集限制了可用的 ABI 标签类型。ABI 标签使用户能够安全地跨翻译单元边界传递数据并行类型的对象。

[编辑] 仅供说明的实体

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) (仅作说明*)
1) /*simd-size-type*/ 是一个有符号整数类型的别名。实现可以自由选择任何有符号整数类型。
2) /*integer-from*/<Bytes> 是一个有符号整数类型 T 的别名,使得 sizeof(T) 等于 Bytes
3) /*simd-size-v*/<T, Abi> 表示已启用特化 basic_simd<T, Abi> 的宽度,否则为 0
4) 如果 T 表示 std::basic_simd_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)xconst T 类型的左值。/*deduced-simd-t*/<T> 是一个等价于以下内容的别名:
  • decltype(x + x),如果 x + x 的类型是 basic_simd 的已启用特化;否则为
  • void.
7)xconst T 类型的左值。/*make-compatible-simd-t*/<V, T> 是一个等价于以下内容的别名:
  • /*deduced-simd-t*/<T>,如果该类型不是 void,否则为
  • std::simd<decltype(x + x), V​::​size()>.
数学函数要求
template< class V >
concept /*simd-floating-point*/ = /* 参阅描述 */;
(8) (仅作说明*)
template< class... Ts >
concept /*math-floating-point*/ = /* 参阅描述 */;
(9) (仅作说明*)
template< class... Ts >

  requires /*math-floating-point*/<Ts...>

using /*math-common-simd-t*/ = /* 参阅描述 */;
(10) (仅作说明*)
template< class BinaryOp, class T >
concept /*reduction-binary-operation*/ = /* 参阅描述 */;
(11) (仅作说明*)
8) 概念 /*simd-floating-point*/ 定义为
template< class V >
concept /*simd-floating-point*/ =
    std::same_as<V, std::basic_simd<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) == 1true
  • 否则,std::common_type_t</*deduced-simd-t*/<T0>, /*deduced-simd-t*/<T1>>,如果 sizeof...(Ts) == 2true/*math-floating-point*/<T0> && /*math-floating-point*/<T1>true
  • 否则,std::common_type_t</*deduced-simd-t*/<T0>, T1>,如果 sizeof...(Ts) == 2true/*math-floating-point*/<T0>true
  • 否则,std::common_type_t<T0, /*deduced-simd-t*/<T1>>,如果 sizeof...(Ts) == 2true
  • 否则,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<T, 1> v) {
        { binary_op(v, v) } -> std::same_as<std::simd<T, 1>>;
    };

/*reduction-binary-operation*/<BinaryOp, T> 仅当满足以下条件时才被建模:

  • BinaryOp 是一个可交换的二元元素级操作,且
  • 类型为 BinaryOp 的对象可使用两个类型为 std::basic_simd<T, Abi> 的参数调用,其中 Abi 是未指定的 ABI 标签,并返回一个 std::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) (仅作说明*)
12) /*native-abi*/<T> 是一个实现定义的 ABI 标签别名。这是用于高效显式矢量化的主要 ABI 标签。因此,basic_simd<T, /*native-abi*/<T>> 是一个已启用的特化。
13) /*deduce-abi-t*/<T, N> 是一个命名 ABI 标签类型的别名,使得
  • /*simd-size-v*/<T, /*deduce-abi-t*/<T, N>> 等于 N
  • std::basic_simd<T, /*deduce-abi-t*/<T, N>> 是一个已启用的特化,且
  • std::basic_simd_mask<sizeof(T), /*deduce-abi-t*/</*integer-from*/<sizeof(T)>, N>> 是一个已启用的特化。
它仅当 T 是可矢量化类型,并且 N > 0 && N <= Mtrue 时定义,其中 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) 数据并行类型和操作

[编辑] 示例

#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::basic_simd<int, A> my_abs(std::basic_simd<int, A> x)
{
    return std::simd_select(x < 0, -x, x);
}
 
int main()
{
    constexpr std::simd<int> a = 1;
    println("a", a);
 
    constexpr std::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::reduce(e);
    std::cout << "inner product: " << inner_product << '\n';
 
    constexpr std::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.  ISO/IEC TS 19570:2018 第 9 节“数据并行类型”的实现 — github.com
2.  TS 实现涵盖 GCC/libstdc++ (std::experimental::simd 随 GCC-11 发布) — gcc.gnu.org