Eigen 的矢量化回退如何工作?
How does Eigen's vectorisation fallback work?
Explicit vectorization is performed for SSE 2/3/4, AVX, FMA, AVX512, ARM NEON (32-bit and 64-bit), PowerPC AltiVec/VSX (32-bit and 64-bit) instruction sets, and now S390x SIMD (ZVector) with graceful fallback to non-vectorized code.
这是否意味着如果你编译,例如使用 FMA,并且 CPU 您正在 运行ning 不支持它,它将回退到完全未向量化的代码?还是会退回到可用的最佳矢量化?
如果没有,有没有办法让 Eigen 为所有或几个 SIMD ISA 编译并在 运行 时间自动选择最好的?
编辑:明确地说,我说的是 运行 时间回退。
Eigen 中绝对没有 run-time 调度。发生的一切都发生在 compile-time。这是您需要通过 preprocessor macros that control the library's behavior 或使用 C++ 编译器中的优化设置做出所有选择的地方。
为了实施 run-time 调度,您需要检查并查看 对库的每次调用 支持哪些 CPU 功能] 并分支到适用的实现中,否则您需要在启动时进行一次此检查并设置 table 函数指针(或其他一些有助于动态调度的方法)。 Eigen 不能做后者,因为它是一个 header-only 库(只是一个 collection 类型和函数),没有 "main" 在初始化时调用的函数,其中所有这些设置代码可以本地化。所以唯一的选择是前者,这将导致 显着 性能损失。这个库的重点是速度;将这种类型的性能损失引入库的每个函数将是一场灾难。
文档还包含 a breakdown of how Eigen works, using a simple example。此页面显示:
The goal of this page is to understand how Eigen compiles it, assuming that SSE2 vectorization is enabled (GCC option -msse2).
这进一步证实了静态 compile-time 选项决定库如何工作的说法。
无论您选择以哪个指令集为目标,生成的代码都会包含这些指令。如果您尝试在不支持这些指令的处理器上执行该代码(例如,您在启用 AVX 优化的情况下编译 Eigen,但您 运行 它在不支持 AVX 指令集的 Intel Nehalem 处理器上执行),那么您将得到一个无效指令异常(以操作系统传递 CPU 异常的任何形式呈现给您的程序)。一旦您的 CPU 遇到 unrecognized/unsupported 指令,这种情况就会发生,该指令可能深入其中一个 Eigen 函数的内部(即,不是在启动时立即出现)。
然而,正如我在评论中所说,有一种回退机制,但它是静态的,都是在编译时完成的。作为 the documentation indicates, Eigen supports multiple vector instruction sets. If you choose a lowest-common-denominator instruction set, like SSE2, you will still get some degree of vectorization. For example, although SSE3 may provide a specialized instruction for some particular task, if you can't target SSE3, all hope is not lost. There is, in many places, code that uses a series of SSE2 instructions to accomplish the same task. These are probably not as efficient as if SSE3 were available, but they'll still be faster than having no vector code whatsoever. You can see examples of this 通过深入研究源代码,特别是 arch
文件夹,其中包含针对不同指令集(通常通过使用内在函数)专门优化的花絮。换句话说,您可以获得它可以为您的目标 architecture/instruction 集提供的最佳代码。
Explicit vectorization is performed for SSE 2/3/4, AVX, FMA, AVX512, ARM NEON (32-bit and 64-bit), PowerPC AltiVec/VSX (32-bit and 64-bit) instruction sets, and now S390x SIMD (ZVector) with graceful fallback to non-vectorized code.
这是否意味着如果你编译,例如使用 FMA,并且 CPU 您正在 运行ning 不支持它,它将回退到完全未向量化的代码?还是会退回到可用的最佳矢量化?
如果没有,有没有办法让 Eigen 为所有或几个 SIMD ISA 编译并在 运行 时间自动选择最好的?
编辑:明确地说,我说的是 运行 时间回退。
Eigen 中绝对没有 run-time 调度。发生的一切都发生在 compile-time。这是您需要通过 preprocessor macros that control the library's behavior 或使用 C++ 编译器中的优化设置做出所有选择的地方。
为了实施 run-time 调度,您需要检查并查看 对库的每次调用 支持哪些 CPU 功能] 并分支到适用的实现中,否则您需要在启动时进行一次此检查并设置 table 函数指针(或其他一些有助于动态调度的方法)。 Eigen 不能做后者,因为它是一个 header-only 库(只是一个 collection 类型和函数),没有 "main" 在初始化时调用的函数,其中所有这些设置代码可以本地化。所以唯一的选择是前者,这将导致 显着 性能损失。这个库的重点是速度;将这种类型的性能损失引入库的每个函数将是一场灾难。
文档还包含 a breakdown of how Eigen works, using a simple example。此页面显示:
The goal of this page is to understand how Eigen compiles it, assuming that SSE2 vectorization is enabled (GCC option -msse2).
这进一步证实了静态 compile-time 选项决定库如何工作的说法。
无论您选择以哪个指令集为目标,生成的代码都会包含这些指令。如果您尝试在不支持这些指令的处理器上执行该代码(例如,您在启用 AVX 优化的情况下编译 Eigen,但您 运行 它在不支持 AVX 指令集的 Intel Nehalem 处理器上执行),那么您将得到一个无效指令异常(以操作系统传递 CPU 异常的任何形式呈现给您的程序)。一旦您的 CPU 遇到 unrecognized/unsupported 指令,这种情况就会发生,该指令可能深入其中一个 Eigen 函数的内部(即,不是在启动时立即出现)。
然而,正如我在评论中所说,有一种回退机制,但它是静态的,都是在编译时完成的。作为 the documentation indicates, Eigen supports multiple vector instruction sets. If you choose a lowest-common-denominator instruction set, like SSE2, you will still get some degree of vectorization. For example, although SSE3 may provide a specialized instruction for some particular task, if you can't target SSE3, all hope is not lost. There is, in many places, code that uses a series of SSE2 instructions to accomplish the same task. These are probably not as efficient as if SSE3 were available, but they'll still be faster than having no vector code whatsoever. You can see examples of this 通过深入研究源代码,特别是 arch
文件夹,其中包含针对不同指令集(通常通过使用内在函数)专门优化的花絮。换句话说,您可以获得它可以为您的目标 architecture/instruction 集提供的最佳代码。