为什么 C++ 标准库中没有 SIMD 功能?

Yam*_*ari 7 c++ stl simd

SSE 自 1999 年以来一直存在,它及其以下扩展是提高 C++ 程序性能的最强大工具之一。然而,没有明确使用此功能的标准化容器/算法等(我知道吗?)。是否有一个原因?是否有一个提案从未通过?

ahc*_*cox 5

(parallelism TS v2) 中有对映射到常见 ISA 的 SIMD 扩展的显式短向量 SIMD 类型的实验支持,但截至 2021 年 8 月,只有 GCC 实现了它。上面链接的 Cppreference 文档不完整,但还有其他详细信息盖在工作草案,技术规范C ++扩展为并行,文献N4808。该提案背后的想法是在博士项目(此处为 2015 年论文)期间开发的。GCC实现的作者写了一篇文章在转换现有的 SSE 字符串处理算法以使用他的库的 2019 年迭代时,实现了类似的性能和更高的可读性。这是一些使用它和生成的程序集的简单代码:

乘加

#include <experimental/simd> // Fails on MSVC 19 and others
using vec4f = std::experimental::fixed_size_simd<float,4>;

void madd(vec4f& out, const vec4f& a, const vec4f& b)
{
    out += a * b;
}

Run Code Online (Sandbox Code Playgroud)

编译-march=znver2 -Ofast -ffast-math我们确实得到了为此生成的硬件融合乘加:

madd(std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_Fixed<4> >&, std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_Fixed<4> > const&, std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_Fixed<4> > const&):
        vmovaps xmm0, XMMWORD PTR [rdx]
        vmovaps xmm1, XMMWORD PTR [rdi]
        vfmadd132ps     xmm0, xmm1, XMMWORD PTR [rsi]
        vmovaps XMMWORD PTR [rdi], xmm0
        ret
Run Code Online (Sandbox Code Playgroud)

点积

点/内积可以简洁地写成:

madd(std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_Fixed<4> >&, std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_Fixed<4> > const&, std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_Fixed<4> > const&):
        vmovaps xmm0, XMMWORD PTR [rdx]
        vmovaps xmm1, XMMWORD PTR [rdi]
        vfmadd132ps     xmm0, xmm1, XMMWORD PTR [rsi]
        vmovaps XMMWORD PTR [rdi], xmm0
        ret
Run Code Online (Sandbox Code Playgroud)

-Ofast -ffast-math -march=znver2

dot_product(std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_Fixed<4> >, std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_Fixed<4> >):
        vmovaps xmm1, XMMWORD PTR [rsi]
        vmulps  xmm1, xmm1, XMMWORD PTR [rdi]
        vpermilps       xmm0, xmm1, 27
        vaddps  xmm0, xmm0, xmm1
        vpermilpd       xmm1, xmm0, 3
        vaddps  xmm0, xmm0, xmm1
        ret
Run Code Online (Sandbox Code Playgroud)

Godbolt 链接与更多的玩耍)。

  • @PeterCordes 代码包含一条注释“以下确保函数参数通过堆栈传递。这对于跨 TU 边界的 ABI 兼容性很重要”:-( (2认同)