只是有趣的是它是如何在游戏和其他软件中工作的。
更准确地说,我需要一个C++
的解决方案。
类似于:
if AMX available -> Use AMX version of the math library
else if AVX-512 available -> Use AVX-512 version of the math library
else if AVX-256 available -> Use AVX-256 version of the math library
etc.
我的基本想法是在不同的DLL中编译库,并在运行时交换它们,但这对我来说似乎不是最好的解决方案。
2条答案
按热度按时间zzzyeukh1#
对于检测部分
请参阅 * Are the xgetbv and CPUID checks sufficient to guarantee AVX2 support? *,其中显示了如何检测CPU和操作系统对新扩展的支持:分别为
cpuid
和xgetbv
。伊萨扩展添加了新的/更宽的寄存器,需要在上下文切换时保存/恢复,这些寄存器也需要得到操作系统的支持和启用,而不仅仅是CPU。如果操作系统没有设置控制寄存器位,像AVX-512这样的新指令在支持它们的CPU上仍然会出错。(有效地承诺它知道它们并将保存/恢复它们。)Intel的设计使故障模式发生故障,而不是CPU迁移时寄存器的无声损坏,或者使用扩展在两个程序之间进行上下文切换。
添加了新的或更宽的寄存器的扩展是AVX、AVX-512 F和AMX。操作系统需要知道它们。(AMX是非常新的,并且添加了大量的状态:8 tile registers T0-T7,每个1 KiB。显然操作系统需要了解AMX for power-management to work properly。)
操作系统不需要知道AVX 2/FMA 3(仍然是YMM 0 -15),或者任何仍然使用k 0-k7和ZMM 0 -31的各种AVX-512扩展。
没有独立于操作系统的方法来检测操作系统对SSE的支持,但幸运的是,它已经足够老了,现在你不必这么做。它和SSE 2是x86-64的基线。直到SSE4.2的所有内容都使用相同的寄存器状态(XMM 0 -15),所以操作系统对SSE 1的支持足以让用户空间使用SSE4.2。SSE 1是1999年新推出的,与Pentium 3一起推出。
不同的编译器有不同的方法来检测CPUID和
xgetbv
。请参见does gcc's __builtin_cpu_supports check for OS support?-不幸的是,没有,只有CPUID,至少当有人问到这个问题时。我会认为这是一个GCC bug,但IDK如果它被报告或修复的话。对于可选使用部件
通常将函数指针设置为指向某些重要函数的选定版本。通过函数指针进行内联通常是不可能的,因此请确保适当地选择边界,例如包含循环而不仅仅是单个向量的函数的AVX-512版本。
GCC的function multi-versioning可以为您自动化这一点,透明地编译多个版本,并挂钩一些函数指针设置。
以前有一些关于不同编译器的问答,搜索“CPU dispatch avx”或类似的内容,沿着其他搜索词。
请参阅使用SSE / AVX内部函数时架构的影响,以了解GCC/clang的内部函数模型与MSVC和经典ICC之间的区别,前者必须启用
-march=skylake
或其他功能,或者手动启用-mavx2
,然后才能使用内部函数,后者可以在任何地方使用任何内部函数,即使是发出编译器无法进行自动矢量化的指令。(这些编译器无法或根本没有对内部函数进行很多优化,这可能是因为这会导致它们从if(cpu)
语句中被提升出来。)izj3ouym2#
Windows提供
IsProcessorFeaturePresent
,但AVX支持不在列表中。更详细的检测需要直接询问CPU。在x86上,这意味着CPUID指令。Visual C++为此提供了
__cpuidex
内在函数。在您的情况下,函数/leaf 1和ECX中的check bit 28。Wikipedia有一个decent article,但您确实应该下载英特尔指令集手册作为参考。