我正在尝试优化一些矩阵计算,并且想知道是否可以在编译时检测SSE / SSE2 / AVX / AVX2 / AVX-512 / AVX-128-FMA / KCVI [1]是否启用编译器?非常适合GCC和Clang,但我只能管理其中之一。

我不确定是否有可能,也许我会使用自己的宏,但是我宁愿检测到它并要求用户选择它。

[1]“KCVI”代表Knights Corner Vector指令优化。诸如FFTW之类的库可检测/利用这些较新的指令优化。

最佳答案

大多数编译器会自动定义:

__SSE__
__SSE2__
__SSE3__
__AVX__
__AVX2__

等等,具体取决于您传递的命令行开关。您可以使用gcc(或gcc兼容的编译器,例如clang)轻松检查此情况,如下所示:
$ gcc -msse3 -dM -E - < /dev/null | egrep "SSE|AVX" | sort
#define __SSE__ 1
#define __SSE2__ 1
#define __SSE2_MATH__ 1
#define __SSE3__ 1
#define __SSE_MATH__ 1

要么:
$ gcc -mavx2 -dM -E - < /dev/null | egrep "SSE|AVX" | sort
#define __AVX__ 1
#define __AVX2__ 1
#define __SSE__ 1
#define __SSE2__ 1
#define __SSE2_MATH__ 1
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE_MATH__ 1
#define __SSSE3__ 1

或仅检查特定平台上默认构建的预定义宏:
$ gcc -dM -E - < /dev/null | egrep "SSE|AVX" | sort
#define __SSE2_MATH__ 1
#define __SSE2__ 1
#define __SSE3__ 1
#define __SSE_MATH__ 1
#define __SSE__ 1
#define __SSSE3__ 1

较新的Intel处理器支持AVX-512,它不是单片指令集。可以从以下两个示例中看到GCC(版本6.2)提供的支持。

这是骑士登陆:
$ gcc -march=knl -dM -E - < /dev/null | egrep "SSE|AVX" | sort
#define __AVX__ 1
#define __AVX2__ 1
#define __AVX512CD__ 1
#define __AVX512ER__ 1
#define __AVX512F__ 1
#define __AVX512PF__ 1
#define __SSE__ 1
#define __SSE2__ 1
#define __SSE2_MATH__ 1
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE_MATH__ 1
#define __SSSE3__ 1

这是Skylake AVX-512:
$ gcc -march=skylake-avx512 -dM -E - < /dev/null | egrep "SSE|AVX" | sort
#define __AVX__ 1
#define __AVX2__ 1
#define __AVX512BW__ 1
#define __AVX512CD__ 1
#define __AVX512DQ__ 1
#define __AVX512F__ 1
#define __AVX512VL__ 1
#define __SSE__ 1
#define __SSE2__ 1
#define __SSE2_MATH__ 1
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE_MATH__ 1
#define __SSSE3__ 1

英特尔已经公开了其他AVX-512子集(请参阅ISA extensions)。 GCC(版本7)支持与AVX-512的4FMAPS,4VNNIW,IFMA,VBMI和VPOPCNTDQ子集相关的编译器标志和预处理器符号:
for i in 4fmaps 4vnniw ifma vbmi vpopcntdq ; do echo "==== $i ====" ; gcc -mavx512$i -dM -E - < /dev/null | egrep "AVX512" | sort ; done
==== 4fmaps ====
#define __AVX5124FMAPS__ 1
#define __AVX512F__ 1
==== 4vnniw ====
#define __AVX5124VNNIW__ 1
#define __AVX512F__ 1
==== ifma ====
#define __AVX512F__ 1
#define __AVX512IFMA__ 1
==== vbmi ====
#define __AVX512BW__ 1
#define __AVX512F__ 1
#define __AVX512VBMI__ 1
==== vpopcntdq ====
#define __AVX512F__ 1
#define __AVX512VPOPCNTDQ__ 1

关于gcc - 如何在编译时检测SSE/SSE2/AVX/AVX2/AVX-512/AVX-128-FMA/KCVI的可用性?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28939652/

10-11 23:23