Data-parallel types (SIMD) (since C++26)
该库提供数据并行类型及对这些类型的操作:通过可移植类型显式声明数据并行性,并在可用时通过数据并行执行资源(例如 SIMD 寄存器和指令,或由通用指令解码器驱动的执行单元)来构建数据结构。
可向量化类型的集合包括:
- 所有标准整数和字符类型;
- 大多数浮点类型,包括 float 、 double 以及选定的扩展浮点类型: std:: float16_t 、 std:: float32_t 和 std:: float64_t (若已定义);以及
-
std::
complex
<
T
>
,其中
T是可向量化的浮点类型。
一个 数据并行类型 由基础可向量化类型(称为 元素类型 )的一个或多个元素组成。元素数量(称为 宽度 )对于每个数据并行类型都是恒定的。
数据并行类型指代所有已启用的类模板
basic_simd
与
basic_simd_mask
的特化形式。
一个数据并行类型的
数据并行对象
的行为类似于类型
T
的对象。但
T
存储和操作单个值,而具有元素类型
T
的数据并行类型则存储和操作多个值。
对数据并行对象的每个操作都采用 逐元素 方式执行(水平操作除外,例如归约操作会明确标注),这些操作会作用于对象的每个元素或两个对象的对应元素。每个此类应用相对于其他应用都是非顺序执行的。这一简单规则体现了数据并行性,编译器将利用该规则生成SIMD指令和/或独立执行流。
所有对数据并行对象的操作(除非常量表达式数学函数重载外)都是 constexpr :可以在常量表达式求值过程中创建和使用数据并行对象。
别名模板
simd
和
simd_mask
的定义允许用户指定特定大小的宽度。默认宽度由实现在编译时确定。
|
定义于头文件
<simd>
|
|
|
定义于命名空间
std::datapar
|
目录主要类
加载和存储标志
加载和存储操作
类型转换
算法
归约操作
排列
特性
数学函数
<cmath>
和
<complex>
中的所有函数均已针对
位操作函数<bit>中的所有位操作函数(除了std::bit_cast)都为
实现细节ABI标签
数据并行类型
ABI标签保持与机器指令集选择无关。所选机器指令集会限制可用的ABI标签类型。ABI标签使用户能够安全地在翻译单元边界传递数据并行类型的对象。
仅用于说明的实体
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
>
是等价于以下类型的别名:
7)
设
x
为类型
const
T
的左值。
/*make-compatible-simd-t*/
<
V, T
>
是等价于以下类型的别名:
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...
>
是等价于以下类型的别名:
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 > 仅在满足以下条件时被建模:
12)
/*native-abi*/
<
T
>
是实现定义的ABI标签别名。这是用于高效显式向量化的主要ABI标签。因此,
basic_simd
<
T,
/*native-abi*/
<
T
>>
是一个已启用的特化。
13)
/*deduce-abi-t*/
<
T, N
>
是一个别名,用于命名满足以下条件的 ABI 标签类型:
T
是可向量化类型且
N
>
0
&&
N
<=
M
为
true
时被定义,其中
M
是实现定义的最大值,该值至少为
64
且可能因
T
而异。
注释
示例
运行此代码
#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 另请参阅
|