Namespaces
Variants

SIMD library

From cppreference.net

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)
指示加载/存储地址按指定对齐方式对齐的标志
(类模板)

Where 表达式

(并行技术规范 v2)
选定元素的非可变操作
(类模板)
(并行技术规范 v2)
选定元素的可变操作
(类模板)
(并行技术规范 v2)
生成 const_where_expression 和 where_expression
(函数模板)

类型转换

(parallelism TS v2)
逐元素 static_cast
(函数模板)
逐元素 ABI 转换
(函数模板)
(parallelism TS v2)
将单个 simd 对象拆分为多个对象
(函数模板)
(parallelism TS v2)
将多个 simd 对象连接为单个对象
(函数模板)

算法

(parallelism TS v2)
逐元素最小值运算
(函数模板)
(parallelism TS v2)
逐元素最大值运算
(函数模板)
(parallelism TS v2)
逐元素最小最大值运算
(函数模板)
(parallelism TS v2)
逐元素钳位运算
(函数模板)

归约

(并行技术规范 v2)
将向量归约为单个元素
(函数模板)

掩码归约

simd_mask 规约到 bool 的归约操作
(函数模板)
(并行性 TS v2)
simd_mask 规约到 true 值数量的归约操作
(函数模板)
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