【问题标题】:Clarifications about SIMD in CC 中关于 SIMD 的说明
【发布时间】:2022-01-21 10:05:18
【问题描述】:

这就是我对 SIMD 的了解。单指令多数据是一种处理数据的方法,它对多个值的向量执行相同的指令。 SIMD 根据机器的处理器(SSE、SSE2、NEON...)在不同级别实现,每个级别提供不同的指令集。

我们可以通过包含immintrin.h 来使用这些指令集。我还没有真正理解的是:在实际使用 SIMD 开发某些东西时,我们是否应该关心检查支持哪些指令集?开发此类程序时的最佳实践是什么?例如,如果不支持指令集,我们应该怎么做;我们应该提供一个非 SIMD 替代方案,还是编译器为我们解向量化整个事情?

【问题讨论】:

  • immintrin.h 是专门的英特尔,而不是 ARM NEON。 (而不是特定于 AMD 的内在函数,例如 Bulldozer 系列的 SSE4a 或 XOP)。
  • @PeterCordes 哦,我明白了,我的英特尔,这就是为什么我从来没有注意到。有没有办法包含 AMD 的?
  • 是的,x86 编译器带有包含 AMD 内容的头文件,但它们基本上已经过时,因为 AMD 在 Zen 中放弃了对 XOP 的支持。现代 AMD CPU 支持 AVX2+FMA3 和 BMI / BMI2,我的意思是 immintrin.h 仅定义 Intel 引入的扩展的内在函数,而不是它们不能在 AMD CPU 上运行。

标签: c simd


【解决方案1】:

当然,我们需要注意支持哪个 ISA,因为如果我们使用未知指令,那么程序将被不支持的指令信号杀死。此外,它还允许我们针对每种架构进行优化,例如在带有 AVX-512 的 CPU 上,我们可以使用 AVX-512 以获得更好的性能,但如果在较旧的 CPU 上,我们可以回退到适合该架构的版本

开发此类程序时的最佳做法是什么?

没有通用的最佳做法。这取决于每种情况,因为每个编译器对此都有不同的工具

  • 如果您的编译器不支持动态调度,那么您需要为每个 ISA 编写单独的代码,并为当前平台调用相应的版本
  • 一些编译器会自动分派到针对运行平台优化的版本,例如 ICC 可以编译一个热循环来分离 SSE/AVX/AVX-512 的版本并跳转到正确的版本以获得最佳性能。
  • 其他一些编译器支持编译为单个函数的不同版本并自动分派,但您需要指定要优化的函数。例如,在 GCC、Clang 和 ICC 中,您可以使用属性 target 和 target_clones。见Building backward compatible binaries with newer CPU instructions support

【讨论】:

【解决方案2】:

我们是否应该关心检查支持哪些指令集?

通常是,但并非总是如此。如果为 PC 编译 64 位代码,则保证有 SSE1 和 SSE2,这两个是 AMD64 指令集的一部分,保证得到支持。

开发此类程序时的最佳做法是什么?

与他人协商您正在开发的软件的最低硬件要求。如果您没有老板、客户或用户,请查找一些统计数据并尝试做出有根据的猜测。 Steam 有一个很好的stats for PC gamers,他们安装了他们的软件,展开“其他设置”,你会看到具有特定指令集的全球用户百分比。

就我个人而言,我认为现在到 2021 年,要求 SSE 达到并包括 SSE 4.1 通常是可以的,如果不支持,则在启动时失败。假设您这样做是优雅的,即在硬件要求中写入,并在运行时向最终用户显示有关不受支持的 CPU 的可理解的错误消息。

我们是否应该提供非 SIMD 替代方案

在过去十年中售出的新计算机中有 99% 至少具有 4GB RAM 和 64 位操作系统。我认为对于大多数项目来说,只发布 64 位二进制文​​件是可以的,这为您提供了 SSE 1 和 2,不需要标量替代方案。

有时,当我需要支持仅 SSE 的 CPU 但 AVX 在性能方面带来了太多利润时,我确实实现了几个替代方案和运行时调度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-07
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 2019-08-29
    • 2019-05-06
    相关资源
    最近更新 更多