SIMD 库
出自 cppreference.cn
< cpp | experimental
SIMD 库为显式声明数据并行性和构造数据以实现更高效的 SIMD 访问提供了可移植的类型。
类型 simd<T> 的对象行为类似于类型 T
的对象。但是,虽然 T
存储和操作单个值,但 simd<T>
存储和操作多个值(称为宽度,但为了与标准库的其余部分保持一致,标识为 size;参见 simd_size)。
simd<T>
上的每个运算符和操作都逐元素执行(水平操作除外,这些操作已明确标记)。这个简单的规则表达了数据并行性,编译器将使用它来生成 SIMD 指令和/或独立的执行流。
类型 simd<T>
和 native_simd<T> 的宽度由实现方式在编译时确定。 相比之下,类型 fixed_size_simd<T, N> 的宽度由开发人员固定为特定大小。
使用不同 SIMD 类型混合以获得高效率的推荐模式是使用 native_simd 和 rebind_simd
#include <experimental/simd> namespace stdx = std::experimental; using floatv = stdx::native_simd<float>; using doublev = stdx::rebind_simd_t<double, floatv>; using intv = stdx::rebind_simd_t<int, floatv>;
这确保了类型集都具有相同的宽度,因此可以相互转换。未定义宽度不匹配的转换,因为它要么会丢弃值,要么必须发明值。对于调整大小的操作,SIMD 库提供了 split 和 concat 函数。
定义于头文件
<experimental/simd> |
目录 |
[编辑] 主要类
(并行性 TS v2) |
数据并行向量类型 (类模板) |
(并行性 TS v2) |
元素类型为 bool 的数据并行类型 (类模板) |
[编辑] ABI 标签
定义于命名空间
std::experimental::simd_abi | |
(并行性 TS v2) |
用于存储单个元素的标签类型 (类型别名) |
(并行性 TS v2) |
用于存储指定数量元素的标签类型 (别名模板) |
(并行性 TS v2) |
确保 ABI 兼容性的标签类型 (别名模板) |
(并行性 TS v2) |
最高效的标签类型 (别名模板) |
(并行性 TS v2) |
保证 fixed 支持的最大元素数量 (常量) |
(并行性 TS v2) |
获取给定元素类型和元素数量的 ABI 类型 (类模板) |
[编辑] 对齐标签
(并行性 TS v2) |
标志,指示加载/存储地址到元素对齐的对齐方式 (类) |
(并行性 TS v2) |
标志,指示加载/存储地址到向量对齐的对齐方式 (类) |
(并行性 TS v2) |
标志,指示加载/存储地址到指定对齐量的对齐方式 (类模板) |
[编辑] Where 表达式
(并行性 TS v2) |
使用非变异操作选择元素 (类模板) |
(并行性 TS v2) |
使用变异操作选择元素 (类模板) |
(并行性 TS v2) |
产生 const_where_expression 和 where_expression (函数模板) |
[编辑] 类型转换
(并行性 TS v2) |
逐元素 static_cast (函数模板) |
(并行性 TS v2) |
逐元素 ABI 转换 (函数模板) |
(并行性 TS v2) |
将单个 simd 对象拆分为多个对象 (函数模板) |
(并行性 TS v2) |
将多个 simd 对象连接成一个对象 (函数模板) |
[编辑] 算法
(并行性 TS v2) |
逐元素 min 操作 (函数模板) |
(并行性 TS v2) |
逐元素 max 操作 (函数模板) |
(并行性 TS v2) |
逐元素 minmax 操作 (函数模板) |
(并行性 TS v2) |
逐元素 clamp 操作 (函数模板) |
[编辑] 归约
(并行性 TS v2) |
将向量归约为单个元素 (函数模板) |
[编辑] 掩码归约
(并行性 TS v2) |
将 simd_mask 归约为 bool (函数模板) |
(并行性 TS v2) |
将 simd_mask 归约为 true 值的数量 (函数模板) |
(并行性 TS v2) |
将 simd_mask 归约为第一个或最后一个 true 值的索引 (函数模板) |
[编辑] 特征
(并行性 TS v2) |
检查类型是否为 simd 或 simd_mask 类型 (类模板) |
(并行性 TS v2) |
检查类型是否为 ABI 标签类型 (类模板) |
(并行性 TS v2) |
检查类型是否为 simd 标志类型 (类模板) |
(并行性 TS v2) |
获取给定元素类型和 ABI 标签的元素数量 (类模板) |
(并行性 TS v2) |
为 vector_aligned 获取适当的对齐量 (类模板) |
(并行性 TS v2) |
更改 simd 或 simd_mask 的元素类型或元素数量 (类模板) |
[编辑] 数学函数
<cmath> 中的所有函数,除了特殊数学函数外,都为 simd
重载。
[编辑] 示例
运行此代码
#include <experimental/simd> #include <iostream> #include <string_view> namespace stdx = std::experimental; void println(std::string_view name, auto const& a) { std::cout << name << ": "; for (std::size_t i{}; i != std::size(a); ++i) std::cout << a[i] << ' '; std::cout << '\n'; } template<class A> stdx::simd<int, A> my_abs(stdx::simd<int, A> x) { where(x < 0, x) = -x; return x; } int main() { const stdx::native_simd<int> a = 1; println("a", a); const stdx::native_simd<int> b([](int i) { return i - 2; }); println("b", b); const auto c = a + b; println("c", c); const auto d = my_abs(c); println("d", d); const auto e = d * d; println("e", e); const auto inner_product = stdx::reduce(e); std::cout << "inner product: " << inner_product << '\n'; const stdx::fixed_size_simd<long double, 16> x([](int i) { return i; }); println("x", x); println("cos²(x) + sin²(x)", stdx::pow(stdx::cos(x), 2) + stdx::pow(stdx::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 |