Namespaces
Variants

Data-parallel types (SIMD) (since C++26)

From cppreference.net

该库提供数据并行类型及对这些类型的操作:通过可移植类型显式声明数据并行性,并在可用时通过数据并行执行资源(例如 SIMD 寄存器和指令,或由通用指令解码器驱动的执行单元)来构建数据结构。

可向量化类型的集合包括:

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

数据并行类型指代所有已启用的类模板 basic_simd basic_simd_mask 的特化形式。

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

对数据并行对象的每个操作都采用 逐元素 方式执行(水平操作除外,例如归约操作会明确标注),这些操作会作用于对象的每个元素或两个对象的对应元素。每个此类应用相对于其他应用都是非顺序执行的。这一简单规则体现了数据并行性,编译器将利用该规则生成SIMD指令和/或独立执行流。

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

别名模板 simd simd_mask 的定义允许用户指定特定大小的宽度。默认宽度由实现在编译时确定。

定义于头文件 <simd>
定义于命名空间 std::datapar

目录

主要类

数据并行向量类型
(类模板)
可指定宽度的 basic_simd 便捷别名模板
(别名模板)
元素类型为 bool 的数据并行类型
(类模板)
可指定宽度的 basic_simd_mask 便捷别名模板
(别名模板)

加载和存储标志

数据并行类型的加载和存储标志
(类模板)
加载和存储操作使用的默认标志
(常量)
在加载和存储操作中启用非值保留转换的标志
(常量)
指示加载-存储地址与某些指定存储对齐到 datapar::alignment 值的标志
(常量)
指示加载-存储地址与某些指定存储对齐到指定对齐值的标志
(变量模板)

加载和存储操作

从连续范围加载元素到 basic_simd
(函数模板)
将元素从 basic_simd 存储到连续范围
(函数模板)

类型转换

将单个数据并行对象拆分为多个对象
(函数模板)
将多个数据并行对象连接为单个对象
(函数模板)

算法

basic_simd 的逐元素最小/最大操作
(函数模板)
basic_simd 的逐元素钳制操作
(函数模板)
使用条件运算符的逐元素选择
(函数模板)

归约操作

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

特性

获取适用于 datapar::flag_aligned 的对齐方式
(类模板)
更改数据并行类型的元素类型
(类模板)
更改数据并行类型的宽度
(类模板)

数学函数

<cmath> <complex> 中的所有函数均已针对 basic_simd 进行了重载。

位操作函数

<bit> 头文件中的所有位操作函数均针对 basic_simd 进行了重载。

实现细节

ABI标签

数据并行类型 basic_simd basic_simd_mask ABI 标签  相关联。这些标签是用于指定数据并行对象大小和二进制表示形式的类型。该设计旨在使大小和二进制表示形式根据目标架构和编译器标志而变化。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 :: datapar :: 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) x 为类型 const T 的左值。 /*deduced-simd-t*/ < T > 是等价于以下类型的别名:
  • decltype ( x + x ) ,若 x + x 的类型是 basic_simd 的已启用特化;否则
  • void
7) x 为类型 const T 的左值。 /*make-compatible-simd-t*/ < V, T > 是等价于以下类型的别名:
  • /*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... >

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::datapar::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... > 是等价于以下类型的别名:
  • sizeof... ( Ts ) == 1 true 时,对应 /*deduced-simd-t*/ < T0 >
  • 否则,当 sizeof... ( Ts ) == 2 true /*math-floating-point*/ < T0 > && /*math-floating-point*/ < T1 > true 时,对应 std:: common_type_t < /*deduced-simd-t*/ < T0 > , /*deduced-simd-t*/ < T1 >>
  • 否则,当 sizeof... ( Ts ) == 2 true /*math-floating-point*/ < T0 > true 时,对应 std:: common_type_t < /*deduced-simd-t*/ < T0 > , T1 >
  • 否则,当 sizeof... ( Ts ) == 2 true 时,对应 std:: common_type_t < T0, /*deduced-simd-t*/ < T1 >>
  • 否则,当 /*math-common-simd-t*/ < T0, T1 > 是有效类型时,对应 std:: common_type_t < /*math-common-simd-t*/ < T0, T1 > , TRest... >
  • 否则,对应 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::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*/ = /* see description */ ;
(12) ( 仅用于说明* )
template < class T, /*simd-size-type*/ N >
using /*deduce-abi-t*/ = /* see description */ ;
(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 :: 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) ( 仅用于说明* )
14-16) 这些标签类型用作 std::datapar::flags 的模板参数。其对应用途请参阅 加载与存储标志

注释

功能测试 标准 功能特性
__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);
    // 重载的数学函数定义在 <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