英特尔至强融核处理器(代号“Knights Landing”)是第二代英特尔至强融核产品的一部分。Knights Landing 支持 AVX-512 指令,特别是 AVX-512F (foundation)、AVX-512CD(冲突检测)、AVX-512ER(指数函数和倒数函数)和 AVX-512PF(预取)。
如果希望应用能够随处运行,为了在程序中使用这些指令,需要确保操作系统和处理器在应用运行时支持这些指令。
英特尔编译器提供的单个函数 _may_i_use_cpu_feature 可轻松处理一切。 该程序显示了我们如何用它来测试是否能够 使用 AVX-512F、AVX-512ER、AVX-512PF 和 AVX-512CD 指令。
#include <immintrin.h> #include <stdio.h> int main(int argc, char *argv[]) { const unsigned long knl_features = (_FEATURE_AVX512F | _FEATURE_AVX512ER | _FEATURE_AVX512PF | _FEATURE_AVX512CD ); if ( _may_i_use_cpu_feature( knl_features ) ) printf("This CPU supports AVX-512F+CD+ER+PF as introduced in Knights Landing\n"); else printf("This CPU does not support all Knights Landing AVX-512 features\n"); return 1; }
如果采用 -xMIC_AVX512 标记进行编译,英特尔编译器将自动保护二进制,无需进行检查。例如,如果按照以下方式编译和运行,我们可以看到机器(并非 Knights Landing)的运行结果。
icc -xMIC-AVX512 -o sample sample.c
./sample
请验证操作系统和处理器是否支持英特尔 MOVBE、F16C、AVX、FMA、BMI、LZCNT、AVX2、AVX512F、ADX、RDSEED、AVX512ER、AVX512PF 和 AVX512CD 指令。
为了在所有处理器上运行,我们按照以下方式编译和运行:
icc -axMIC-AVX512 -o sample sample.c
./sample
在 Knights Landing 上运行时,将显示:
This CPU supports AVX-512F+CD+ER+PF as introduced in Knights Landing
在不支持 AVX-512 指令,但至少相当于 Knights Landing 的处理器上运行时,将显示:
该 CPU 不支持所有 Knights Landing AVX-512 特性
如果我们希望支持除英特尔之外的编译器,代码将稍微复杂一些,因为函数 _may_i_use_cpu_feature 不是标准函数(而且两个都不是 gcc 和 clang/LLVM 的 __buildin 函数)。以下代码至少适用于英特尔编译器、gcc、clang/LLVM 和 Microsoft 编译器。
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300) #include <immintrin.h> int has_intel_knl_features() { const unsigned long knl_features = (_FEATURE_AVX512F | _FEATURE_AVX512ER | _FEATURE_AVX512PF | _FEATURE_AVX512CD ); return _may_i_use_cpu_feature( knl_features ); } #else /* non-Intel compiler */ #include <stdint.h> #if defined(_MSC_VER) #include <intrin.h> #endif void run_cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd) { #if defined(_MSC_VER) __cpuidex(abcd, eax, ecx); #else uint32_t ebx, edx; #if defined( __i386__ ) && defined ( __PIC__ ) /* in case of PIC under 32-bit EBX cannot be clobbered */ __asm__ ( "movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi" : "=D" (ebx), # else __asm__ ( "cpuid" : "+b" (ebx), # endif"+a" (eax), "+c" (ecx), "=d" (edx) ); abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx; #endif } int check_xcr0_zmm() { uint32_t xcr0; uint32_t zmm_ymm_xmm = (7 << 5) | (1 << 2) | (1 << 1); #if defined(_MSC_VER) xcr0 = (uint32_t)_xgetbv(0); /* min VS2010 SP1 compiler is required */ #else __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" ); #endif return ((xcr0 & zmm_ymm_xmm) == zmm_ymm_xmm); /* check if xmm, zmm and zmm state are enabled in XCR0 */ } int has_intel_knl_features() { uint32_t abcd[4]; uint32_t osxsave_mask = (1 << 27); // OSX. uint32_t avx2_bmi12_mask = (1 << 16) | // AVX-512F (1 << 26) | // AVX-512PF (1 << 27) | // AVX-512ER (1 << 28); // AVX-512CD run_cpuid( 1, 0, abcd ); // step 1 - must ensure OS supports extended processor state management if ( (abcd[2] & osxsave_mask) != osxsave_mask ) return 0; // step 2 - must ensure OS supports ZMM registers (and YMM, and XMM) if ( ! check_xcr0_zmm() ) return 0; return 1; } #endif /* non-Intel compiler */ static int can_use_intel_knl_features() { static int knl_features_available = -1; /* test is performed once */ if (knl_features_available < 0 ) knl_features_available = has_intel_knl_features(); return knl_features_available; } #include <stdio.h> int main(int argc, char *argv[]) { if ( can_use_intel_knl_features() ) printf("This CPU supports AVX-512F+CD+ER+PF as introduced in Knights Landing\n"); else printf("This CPU does not support all Knights Landing AVX-512 features\n"); return 1; }
致谢:感谢 Max Locktyukhin(英特尔)的文章 -“如何检测第四代智能英特尔酷睿处理器家族的新指令支持”,我将其用作 Knights Landing 检测代码的模型。