simde:基于 SIMD 技术的跨平台指令集兼容库项目

用户可轻松在不同架构硬件上运行特定SIMD指令集代码,无需重写。该项目提供快速、可移植的SIMD内在函数实现,支持多指令集,原生硬件支持时无性能损失,助力代码跨架构移植与优化。【此简介由AI生成】

分支1Tags1
文件最后提交记录最后更新时间
1 年前
1 年前
1 年前
1 年前
1 年前
11 个月前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
11 个月前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前
1 年前

SIMD 到处都是

所有贡献者

聊天 codecov

SIMDe 头文件库提供了快速的、可移植的 SIMD 内联函数实现,适用于不支持它们的硬件,例如在 ARM 上调用 SSE 函数。如果硬件支持本地实现,则没有性能损失(例如,SSE/AVX 在 x86 上,NEON 在 ARM 上运行速度全速)。

这使得将代码移植到其他架构变得更加容易,主要体现在以下几个方面:

首先,SIMDe 允许您几乎不费力地将端口搭建起来并运行,而不是强迫您为每个架构重写所有内容。然后,您可以开始将性能最关键的部分切换到本地内联函数,逐渐提高性能。SIMDe 使得(例如)SSE/AVX 和 NEON 代码可以并存在同一实现中。

其次,SIMDe 使得编写针对您无法方便访问的 ISA 扩展的代码变得更加容易。您可以在没有模拟器的情况下在 x86 机器上运行 NEON 代码。显然,您最终需要在目标硬件上进行测试,但对于大多数开发工作,SIMDe 可以提供一条更轻松的路径。

SIMDe 与大多数其他 SIMD 抽象层不同的地方在于,它旨在暴露底层指令集的完整功能。SIMDe 试图在保持可移植性的同时,减少移植所需的工作量,同时给您留出优化的空间。

当前的重点是编写完整的可移植实现,尽管已经有大量函数使用以下一种或多种方法实现了加速:

您可以使用 Compiler Explorer 和一个混合的 SIMDe 头文件在线尝试 SIMDe。

如果您有任何问题,请随时使用 问题跟踪器邮件列表

当前状态

目前以下指令集扩展已有完整的实现:

以及其他许多指令集扩展的部分支持,包括 AES-ni、CLMUL、SSE4.2、SVE、MSA 以及几个 AVX-512 扩展。有关进展详情,请查看问题跟踪器中的 指令集支持 标签。如果您希望收到某个指令集可用时的通知,您可以通过订阅相关问题来做到这一点。

如果您有兴趣使用 SIMDe 但我们尚未支持您需要的所有函数,请提交一个包含所需内容的列表的问题,以便我们知道要优先处理哪些内容。

默认分支受到保护,除非经过广泛的 CI 检查,否则提交不会到达该分支。状态徽章实际上没有意义,因为它们始终为绿色,但以下是链接:

如果您正在添加新的构建,我建议使用 Cirrus CI,因为我们目前在平台上拥有最多的空间,考虑到当前构建数量和免费/开源使用的配额。或者,您可以自由设置其他提供者(例如 CodefreshShippableBitriseWerkaer 等)。

注意:我们计划将默认分支的名称从“master”更改为其他名称,我们只是在等待 git 确定名称,以便我们可以保持一致性。

贡献指南

首先,非常感谢您阅读这一部分内容。考虑到为 SIMDe 项目做出贡献,本身就已经是非常宝贵的!

SIMDe 是一个相当庞大的项目;有大量的函数需要处理,并且在不同平台上有很多优化机会,所以我们非常欢迎您提供的任何帮助。

欢迎各技能水平的程序员参与,有很多任务相对直接明了,不需要任何特殊专长。

如果您不确定要以何种方式贡献,请考虑查看 问题追踪器。有一个 好的第一个问题 标签,如果您想逐步开始您的首次贡献,但如果您对其他方面感兴趣,请通过问题追踪器与我们联系;我们很乐意帮助您了解您感兴趣的任何内容。

如果您对实现当前未实现的函数感兴趣,有一个 指南 解释了如何添加新函数以及如何快速轻松地设置测试用例。目前这个指南还比较粗糙,但如果有什么不清楚的地方,请随时使用问题追踪器询问任何您不清楚的问题。

使用说明

首先,重要的是要注意,您 不需要两个独立的版本(一个使用 SIMDe,另一个是原生版本)。如果原生函数可用,SIMDe 将使用它们,编译器可以轻松地优化掉 SIMDe 的任何开销;它们需要做的只是基本的内联。-O2 应该就足够了,但我们强烈推荐 -O3(或任何指示编译器进行积极优化的标志),因为许多可移植回退在启用积极自动矢量化时(在较低的优化级别下不启用)速度会更快。

每个指令集都有一个单独的文件;例如 x86/mmx.h 对应 MMX,x86/sse.h 对应 SSE,x86/sse2.h 对应 SSE2,依此类推。只需包含您想要使用的指令集的头文件 而不是原生版本(如果您在包含 SIMDe 之后包含原生版本,如果启用了原生别名,将导致编译时错误)。SIMDe 将根据您在编译器中启用的扩展提供最快的实现(例如,如果您想使用 NEON 来实现 SSE,您可能需要传递类似 -mfpu=neon-march=armv8-a+simd 的参数。更多信息请参见 GCC ARM 选项)。

如果您在包含 SIMDe 之前定义了 SIMDE_ENABLE_NATIVE_ALIASES,您可以使用与原生函数相同的名称。不幸的是,由于 API 的可移植性问题,这有点容易出错,因此建议只将此选项用于测试。当未定义 SIMDE_ENABLE_NATIVE_ALIASES 时,只有以 simde_ 前缀的版本可用;例如,MMX 的 _mm_add_pi8 内部函数变为 simde_mm_add_pi8__m64 变为 simde__m64

由于 SIMDe 是为了可移植性而设计,许多假设类型具有特定大小的函数已被修改为使用固定宽度类型。例如,Intel 的 API 使用 char 表示有符号 8 位整数,但在 ARM 上 char 通常是无符号的。SIMDe 使用 int8_t 来使 API 可移植,这意味着您的代码可能需要进行一些小的更改(例如,使用 int8_t 而不是 char)才能在其他平台上工作。

尽管如此,这些更改通常非常小。通常只需使用搜索和替换即可,很少需要手动更改。

OpenMP 4 SIMD

SIMDe 大量使用注释来帮助编译器向量化代码。到目前为止,最佳的注释是内置于 OpenMP 4 的 SIMD 支持,所以如果您的编译器支持这些注释,我们强烈建议您启用它们。

如果您已经在使用 OpenMP,SIMDe 将自动使用 _OPENMP 宏检测它,无需进一步操作。

有些编译器允许您在没有启用完整 OpenMP 的情况下启用 OpenMP SIMD。在这种情况下,SIMDe 没有运行时依赖性,也没有运行时开销;SIMDe 只会更快。不幸的是,SIMDe 没有办法检测这种情况(_OPENMP 宏未定义),所以您在编译器中启用它后,需要定义 SIMDE_ENABLE_OPENMP(例如,通过传递 -DSIMDE_ENABLE_OPENMP)以让 SIMDe 输出相关的编译指示。

启用 OpenMP SIMD 支持的方法因编译器而异:

  • GCC 4.9+ 和 clang 6+ 支持 -fopenmp-simd 命令行标志。
  • ICC 支持 -qopenmp-simd 命令行标志。
  • MCST 的 LCC 默认启用 OpenMP SIMD,因此不需要任何标志(技术上您甚至不需要传递 -DSIMDE_ENABLE_OPENMP)。

我们目前不知道还有哪些编译器允许您在不启用完整 OpenMP 的情况下启用 OpenMP SIMD 支持(如果您知道,请提交一个问题告诉我们)。您应该根据具体情况决定是否要启用完整的 OpenMP 支持,但很可能链接到(但不使用)OpenMP 运行时库的开销会被使用 OpenMP SIMD 注释在 SIMDe 中获得的性能提升所抵消。

如果您选择不使用 OpenMP SIMD,SIMDe 还支持使用 Cilk PlusGCC 循环特定编译指示clang 循环提示编译指示,尽管这些不如 OpenMP SIMD 有效,且依赖它们可能会导致代码效率较低。所有这些都会被 SIMDe 自动检测,所以如果它们在您的编译器中已启用,则无需采取进一步措施。

如果出于某种原因您不希望启用 OpenMP 4 SIMD 支持,即使 SIMDe 检测到它,您也应该在包含 SIMDe 之前定义 SIMDE_DISABLE_OPENMP

可移植性

编译器

SIMDe 依赖于一些 C99 特性,尽管 MSVC 支持的子集也能正常工作。虽然我们尽力确保在支持的地方提供优化的实现,但 SIMDe 包含了旨在在任何 C99 编译器上工作的可移植回退。

每个提交都会在持续集成中测试多个编译器、平台和配置,我们的测试覆盖率非常广泛。目前测试的编译器包括:

  • GCC 版本回溯至 4.8
  • Clang 版本回溯至 3.8
  • Microsoft Visual Studio 版本回溯至 12(2013)
  • IBM XL C/C++
  • Intel C/C++ 编译器(ICC)

我通常愿意接受添加其他编译器支持的补丁,只要它们不是太破坏性的,特别是如果我们能够开始 CI 支持。如果使用我们现有的 CI 提供商不可行,那么可以添加其他 CI 平台。

硬件

以下架构在每次提交时都会在持续集成中测试:

  • x86_64/amd64
  • x86
  • AArch64
  • ARMv8
  • ARMv7 支持 VFPv3-D16 浮点数
  • ARMv5 EABI
  • PPC64
  • z/Architecture(带有 "-mzvector")
  • MIPS Loongson 64
  • RISC-V 64
  • emscripten 32位和64位;标准和宽松

我们非常愿意添加更多架构,所以补丁是非常受欢迎的!

相关项目

  • portable-snippets 中的 "builtins" 模块与 SIMDe 做得非常相似,但它针对的是编译器特定的内联函数(例如 __builtin_clz_BitScanForward),不是 SIMD 内联函数。
  • 英特尔提供了一个模拟器,即 Intel® Software Development Emulator,可以用来开发使用英特尔内联函数的软件,而无需拥有支持它们的硬件,尽管它在部署方面无能为力。
  • Iris 是我所知的唯一另一个尝试创建类似 SIMDe 的可移植实现的项目。SIMDe 在英特尔方面的进展要远些,但 Iris 在 ARM 上看起来更完善。仅支持 C++,采用 Apache 2.0 许可证。据我所知,它没有加速的备用方案,也没有简单的方法添加它们,因为它严重依赖模板。
  • 有几个项目尝试使用另一个集合实现:
    • ARM_NEON_2_x86_SSE — 使用 SSE 实现 NEON。相当广泛,采用 Apache 2.0 许可证。
    • sse2neon — 使用 NEON 实现 SSE。这部分代码已经被合并到 SIMDe 中。
    • veclib — 使用 AltiVec/VMX 实现 SSE2,使用非自由的 IBM 库 powerveclib
    • SSE-to-NEON — 使用 NEON 实现 SSE。非自由,采用 C++。
    • AvxToNeon — 用 NEON 实现流行的 AVX+ 内联函数。采用 C 语言,Apache 2.0 许可证。
    • neon2rvv - 一个 C/C++ 头文件,将 Arm/Aarch64 NEON 内联函数转换为 RISC-V Vector (RVV) 扩展,MIT 许可证。
    • sse2rvv - 一个 C/C++ 头文件,将英特尔 SSE 内联函数转换为 RISCV-V 扩展内联函数,MIT 许可证。
  • arm-neon-tests 包含用于验证 NEON 实现的测试。

如果你知道其他相关项目,请 告诉我们

注意事项

有时特性无法模拟。如果 SIMDe 处于原生模式,函数将按预期工作,但如果没有原生支持,则有一些注意事项:

  • 许多函数需要 <math.h> 和/或 <fenv.h>。SIMDe 在没有这些头文件的情况下仍然可以工作,但这些函数的结果是未定义的。
  • x86 / x86_64
    • SSE
      • SIMDE_MM_SET_ROUNDING_MODE() 将使用 fesetround(),改变全局舍入模式。
      • simde_mm_getcsrsimde_mm_setcsr 只实现了位 13 和 14(舍入模式)。
    • AVX
      • simde_mm256_test* 不设置 CF/ZF 寄存器,因为没有可移植的方法实现该功能。
      • simde_mm256_zeroallsimde_mm256_zeroupper 没有实现,因为没有可移植的方法实现该功能。

另外,使用原生别名 (SIMDE_ENABLE_NATIVE_ALIASES) 时也有一些已知的限制:

  • 在 Windows x86(而非 x86_64)上,一些 MMX 函数和 SSE/SSE2 使用 MMX 类型 (__m64)(除指针外)的函数可能会返回不正确的结果。

如前所述,尽管一些 API 假设基本类型(例如,int 为 32 位),SIMDe 并没有这样做,因此许多类型已被修改为使用可移植的固定宽度版本,如 int32_t

如果你发现任何其他差异,请提交一个 issue,以便我们可以修复或将其添加到上面的列表中。

捐助者

SIMDe 使用一些组织免费提供的资源。虽然这不应该被理解为对 SIMDe 的认可,但我们非常感激他们的支持:

如果没有这些组织捐赠资源,SIMDe 将不会像今天这样有用或易于使用。

我们还感谢任何帮助开发 SIMDe 依赖的众多软件的人,包括编译器和分析工具。

最后,特别感谢 任何贡献者 对 SIMDe 的贡献,提交 bug,提供建议,或以任何方式帮助 SIMDe 开发。

许可

SIMDe 采用 MIT 风格的许可证;请参阅 COPYING 文件了解详情。

贡献者 ✨

感谢以下出色的人(表情关键词):


Evan Nemerson

💻 🖋 📖 💡 🤔 💬 👀 ⚠️ 📢 🐛 🚇 🚧 📆

Michael R. Crusoe

🐛 💻 📋 🔍 🤔 🚇 📦 ⚠️ 🚧 📆 👀

HIMANSHI MATHUR

💻 ⚠️

Hidayat Khan

💻 ⚠️

rosbif

💻 ⚠️ 🐛 🤔 📖

Jun Aruga

💻 🤔 📦 🚇 🚧 ⚠️ 🐛

Élie ROUDNINSKI

💻 ⚠️
Jesper Storm Bache

💻
Jeff Daily

💻 🚇
Pavel

💻
Sabarish Bollapragada

💻
Gavin Li

💻
Yining Karl Li

💻
Anirban Dey

📖
Darren Ng

📖
FaresSalem

📖
Pradnyesh Gore

💻
Sean Maher

💻
Mingye Wang

📖
Ng Zhi An

💻 📖
Atharva Nimbalkar

💻 ⚠️
simba611

💻 ⚠️
Ashleigh Newman-Jones

💻 ⚠️
Willy R. Vasquez

💻 🚧 ⚠️
Keith Winstein

💻 🚧 ⚠️
David Seifert

🚧
Milot Mirdita

💻 🚧 ⚠️
aqrit

💻 🚧
Décio Luiz Gazzoni Filho

💻 🚧 ⚠️
Igor Molchanov

💻 🚧 📦
Andrew Rodriguez

💻 🚧 ⚠️
Changqing Jing

🚧
JP Cimalando

💻 🚇
Jiaxun Yang

💻 📦
Masahiro Kitagawa Pavel Iatchenii Tommy Vercetti Robert Cohn Adam Novak boris-kuz
📦💻⚠️ 📦💻⚠️ 🚧 🚧 📖 🚧
Dimo Markov dblue zekehul Laurent Thomas Sam Clegg Thomas Lively
🚧 🚧 💻🚧 💻 🚧 🐛🤔🚧
coderzh Dominik Kutra Lithrein Nick Stephen John Platts
💻⚠️ 💻⚠️ 🚧 🚧 🐛 🐛
Steven Noonan p0nce Paul Wise Devin (easyaspi314) JonLiu1993 Cheney Wang
🐛 🐛 🐛 🐛💻 📦 📦
myd7349 chausner Yi-Yen Chung Chi-Wei Chu M-HT Simon Gene Gottlieb
📦 📦 💻⚠️ 💻⚠️ 💻 💻
--------------------------- --------------------------- ---------------------------
Chris Bielow gu xiwei George Vinokhodov
Chris Bielow gu xiwei George Vinokhodov
💻 代码贡献 📦 新平台打包/移植 ⚠️ 测试 💻 代码贡献
Cœur Florian @Proudsalsa Thomas Schlichter
Cœur Florian @Proudsalsa Thomas Schlichter
💻 代码贡献 💻 代码贡献 🐛 错误报告 💻 代码贡献

本项目遵循 all-contributors 规范。欢迎各种类型的贡献!

项目介绍

用户可轻松在不同架构硬件上运行特定SIMD指令集代码,无需重写。该项目提供快速、可移植的SIMD内在函数实现,支持多指令集,原生硬件支持时无性能损失,助力代码跨架构移植与优化。【此简介由AI生成】

定制我的领域