确定哪个内在标志被激活

Com*_*ist 1 c++ gcc sse intrinsics

在详细说明细节之前,我有以下功能,

令 _e, _w 为大小相等的数组。令 _stepSize 为 float 类型。

void GradientDescent::backUpWeights(FLOAT tdError) {
  AI::FLOAT multiplier = _stepSize * tdError;
  for (UINT i = 0; i < n; i++){
    _w[i] += _e[i]*multiplier
  }

  // Assumed that the tilecode ensure that _w.size() or _e.size() is even.
}
Run Code Online (Sandbox Code Playgroud)

这个函数很好,但是如果一个CPU有内在的,特别是对于这个例子,SSE4,那么下面的函数可以让我减少几秒钟的时间(对于相同的输入),即使-O3 gcc标志已经包含在两个和额外的-msse4a中为此添加了。

void GradientDescent::backUpWeights(FLOAT tdError) {
  AI::FLOAT multiplier = _stepSize * tdError;
  __m128d multSSE = _mm_set_pd(multiplier, multiplier);
  __m128d* eSSE = (__m128d*)_e;
  __m128d* wSSE = (__m128d*)_w;
  size_t n = getSize()>>1;
  for (UINT i = 0; i < n; i++){
    wSSE[i] = _mm_add_pd(wSSE[i],_mm_mul_pd(multSSE, eSSE[i]));
  }

  // Assumed that the tilecode ensure that _w.size() or _e.size() is even.
}
Run Code Online (Sandbox Code Playgroud)

问题:

我现在的问题是我想要这样的东西,

void GradientDescent::backUpWeights(FLOAT tdError) {
AI::FLOAT multiplier = _stepSize * tdError;
#ifdef _mssa4a_defined_
  __m128d multSSE = _mm_set_pd(multiplier, multiplier);
  __m128d* eSSE = (__m128d*)_e;
  __m128d* wSSE = (__m128d*)_w;
  size_t n = getSize()>>1;
  for (UINT i = 0; i < n; i++){
    wSSE[i] = _mm_add_pd(wSSE[i],_mm_mul_pd(multSSE, eSSE[i]));
  }
#else  // No intrinsic
  for (UINT i = 0; i < n; i++){
    _w[i] += _e[i]*multiplier
  }
#endif

  // Assumed that the tilecode ensure that _w.size() or _e.size() is even.
}
Run Code Online (Sandbox Code Playgroud)

因此,如果在 gcc 中,我声明 -msse4a 来编译此代码,那么它会选择编译 if 语句中的代码。当然,我的计划是针对所有内在的实现它,而不仅仅是针对上面的 SSE4A。

Z b*_*son 5

GCC、ICC(在 Linux 上)和 Clang 具有以下编译选项和相应的定义

options       define
-mfma         __FMA__
-mavx2        __AVX2__
-mavx         __AVX__
-msse4.2      __SSE4_2__
-msse4.1      __SSE4_1__
-mssse3       __SSSE3__
-msse3        __SSE3__
-msse2        __SSE2__
-m64          __SSE2__
-msse         __SSE__    
Run Code Online (Sandbox Code Playgroud)

GCC 和 Clang 中的选项和定义,但 ICC 中没有:

-msse4a       __SSE4A__
-mfma4        __FMA4__
-mxop         __XOP__
Run Code Online (Sandbox Code Playgroud)

在最新版本的 GCC、Clang 和 ICC 中定义的 AVX512 选项

-mavx512f     __AVX512F__    //foundation instructions
-mavx512pf    __AVX512PF__   //pre-fetch instructions
-mavx512er    __AVX512ER__   //exponential and reciprocal instructions 
-mavx512cd    __AVX512CD__   //conflict detection instructions
Run Code Online (Sandbox Code Playgroud)

AVX512 选项可能很快就会出现在 GCC、Clang 和 ICC 中(如果还没有)

-mavx512bw    __AVX512BW__   //byte and word instructions
-mavx512dq    __AVX512DQ__   //doubleword and quadword Instructions
-mavx512vl    __AVX512VL__   //vector length extensions
Run Code Online (Sandbox Code Playgroud)

请注意,其中许多开关还启用更多功能:例如-mfma启用和定义 AVX2、AVX、SSE4.2 SSE4.1、SSSE3、SSE3、SSE2、SSE。

我不是 100% 知道 AVX512 的 ICC 编译器选项是什么。它可以-xMIC-AVX512代替-mavx512f.

MSVC 似乎只定义 __AVX__ 和 __AVX2__

在您的情况下,您的代码似乎仅使用 SSE2,因此如果您在 64 位模式下编译(这是 64 位用户空间中的默认设置或使用 显式指定-m64),则已__SSE2__定义。但既然你使用了-msse4athen__SSE4A__也会被定义。

请注意,启用指令与确定指令集是否可用不同。如果您希望代码在多个指令集上运行,那么我建议使用 CPU 调度程序