自动使用 AVX/SSE(如果在运行时可用)

Automatically use AVX/SSE if available at runtime?

本文关键字:如果 运行时 SSE AVX      更新时间:2023-10-16

Dupe of 在同一个可执行文件中使用 C/C++ 具有不同的优化(普通、SSE、AVX)

"自动复制"认为选择了错误的建议重复,我似乎没有界面来修复它。


有没有办法构建一个应用程序,该应用程序可以选择使用指令集扩展(如果可用),但在没有指令集扩展的情况下仍然可以运行(尽管速度更慢)?

现在,我有一个 MSVC++ 雷达成像应用程序,它可以做很多数学运算,可以从矢量化中受益。如果我使用 AVX 编译应用程序,那么当在缺少这些 CPU 功能的平台上运行时,它会在应用程序启动时崩溃。

有没有办法让编译器同时生成 AVX 加速指令和普通指令,并在运行时在它们之间切换?似乎唯一的其他选择是拥有两个完整的应用程序版本,并根据 CPU 架构选择要安装的版本,但这听起来比它值得的麻烦更多。

至少对于我知道的编译器,不,它们不会生成代码来自动检测和利用可用的指令集(至少从完全可移植的代码 - 请参阅下文了解更多信息)。

通常

,将应用程序的数字、CPU 密集型部分移动到 DLL 中,并且仅在运行时选择这些部分,而不是应用程序的两个完整版本。这使得 UI 和类似的东西(并没有真正受益于特殊说明)存在于一个公共区域,并且只有您关心的几个特定部分在运行时被切换掉。

由于您标记了C++,我将提到一种可能的方法来管理它:定义一个抽象基类,该基类定义数字例程的接口。然后为您关心的每个指令集定义一个派生类。

然后在运行时,您有一个指向基的指针。初始化代码检查可用的 CPU,并初始化该指针以指向正确类型的派生对象的实例。从那时起,您只需通过该指针与例程进行交互。

为了避免增加过多的开销,您通常希望在该类(或这些类,视情况而定)中定义您的函数,以每个函数执行相当多的工作,以将虚拟函数调用的额外成本分摊到大量工作上。

不过,您通常不必参与诸如直接致电LoadLibrary之类的事情。可以使用 /Delayload 链接器标志告诉它仅在实际调用 DLL 中的函数时加载 DLL。然后,将仅加载与实例化的派生类对应的 DLL。

另一个明显的可能性是使用像Cilk Plus这样的库/编译器扩展来为您管理大部分矢量化。有了这个,你可以(例如)写这样的东西:

a[:] = b[:] + c[:];

。得到大致相当于:

for (int i=0; i<size; i++)
    a[i] = b[i] + c[i];

编译器链接到 Cilk Plus 库,该库负责检查 CPU 支持的指令集,并根据需要使用它们。

相关文章: