SIMD library
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>
|
目录 |
主要类
|
(parallelism TS v2)
|
数据并行向量类型
(类模板) |
|
(parallelism TS v2)
|
元素类型为 bool 的数据并行类型
(类模板) |
ABI 标签
|
定义于命名空间
std::experimental::simd_abi
|
|
|
(并行 TS v2)
|
用于存储单个元素的标签类型
(类型别名) |
|
(并行 TS v2)
|
用于存储指定数量元素的标签类型
(别名模板) |
|
(并行 TS v2)
|
确保ABI兼容性的标签类型
(别名模板) |
|
(并行 TS v2)
|
最高效的标签类型
(别名模板) |
|
(并行 TS v2)
|
fixed 保证支持的最大元素数量
(常量) |
|
(并行 TS v2)
|
根据给定元素类型和元素数量推导ABI类型
(类模板) |
对齐标签
|
(parallelism TS v2)
|
指示加载/存储地址按元素对齐的标志
(类) |
|
(parallelism TS v2)
|
指示加载/存储地址按向量对齐的标志
(类) |
|
(parallelism TS v2)
|
指示加载/存储地址按指定对齐方式对齐的标志
(类模板) |
Where 表达式
|
(并行技术规范 v2)
|
选定元素的非可变操作
(类模板) |
|
(并行技术规范 v2)
|
选定元素的可变操作
(类模板) |
|
(并行技术规范 v2)
|
生成 const_where_expression 和 where_expression
(函数模板) |
类型转换
|
(parallelism TS v2)
|
逐元素 static_cast
(函数模板) |
|
(parallelism TS v2)
|
逐元素 ABI 转换
(函数模板) |
|
(parallelism TS v2)
|
将单个 simd 对象拆分为多个对象
(函数模板) |
|
(parallelism TS v2)
|
将多个 simd 对象连接为单个对象
(函数模板) |
算法
|
(parallelism TS v2)
|
逐元素最小值运算
(函数模板) |
|
(parallelism TS v2)
|
逐元素最大值运算
(函数模板) |
|
(parallelism TS v2)
|
逐元素最小最大值运算
(函数模板) |
|
(parallelism TS v2)
|
逐元素钳位运算
(函数模板) |
归约
|
(并行技术规范 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
|