Knights Landing のインテル® AVX-512 サポートを検出する方法 (インテル® Xeon Phi™ プロセッサー)

同カテゴリーの次の記事

等方性 3 次元有限差分 (3DFD) 波動方程式コード向けの NUMA を理解する

この記事は、インテル® デベロッパー・ゾーンに公開されている「How to detect Knights Landing AVX-512 support (Intel® Xeon Phi™ processor)」の日本語参考訳です。


インテル® Xeon Phi™ プロセッサー (開発コード名: Knights Landing) は、第 2 世代インテル® Xeon Phi™ 製品の 1 つです。Knights Landing は、AVX-512F (基本)、AVX-512CD (競合検出)、AVX-512ER (指数および逆数)、AVX-512PF (プリフェッチ) のインテル® AVX-512 命令をサポートします。

アプリケーションがこれらの命令を使用する場合、アプリケーション実行時にオペレーティング・システムとプロセッサーがインテル® AVX-512 をサポートしていることを確認する必要があります。

インテル® コンパイラーは、これらを簡単にチェックできる関数 _may_i_use_cpu_feature を用意しています。このプログラムでは、_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

Please verify that both the operating system and the processor support Intel(R) MOVBE, F16C, AVX, FMA, BMI, LZCNT, AVX2, AVX512F, ADX, RDSEED, AVX512ER, AVX512PF and AVX512CD instructions.
(オペレーティング・システムとプロセッサーの両方がインテル(R) MOVBE, F16C, AVX, FMA, BMI, LZCNT, AVX2, AVX512F, ADX, RDSEED, AVX512ER, AVX512PF および AVX-512CD をサポートしていることを確認してください)

すべてのプロセッサー上で実行するには、次のようにコンパイルします:

icc -axMIC-AVX512 -o sample sample.c
./sample

Knights Landing で実行した際の表示:
This CPU supports AVX-512F+CD+ER+PF as introduced in Knights Landing

Knights Landing と同等でインテル® AVX-512 をサポートしないプロセッサー上で実行した際の表示:
This CPU does not support all Knights Landing AVX-512 features

_may_i_use_cpu_feature は標準関数ではないため (gcc と clang/LLVM では __builtin 関数ではない)、インテル以外のコンパイラーをサポートする場合はコードが少し複雑になります。次のコードは、少なくともインテル® コンパイラー、gcc、clang/LLVM、そしてマイクロソフト・コンパイラーでコンパイルできます。

#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 (Intel) による記事「How to detect New Instruction support in the 4th generation Intel® Core™ processor family」を参考にして Knights Landing を識別するように修正しました。

開発コード名

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事