c++ - 确定什么内在标志被激活

标签 c++ gcc sse intrinsics

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

Let _e, _w be an array of equal size. Let _stepSize be of float type.

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.
}

这个函数很好,但是如果一个 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.
}

问题:

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

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.
}

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

最佳答案

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__    

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

-msse4a       __SSE4A__
-mfma4        __FMA4__
-mxop         __XOP__

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

-mavx512f     __AVX512F__    //foundation instructions
-mavx512pf    __AVX512PF__   //pre-fetch instructions
-mavx512er    __AVX512ER__   //exponential and reciprocal instructions 
-mavx512cd    __AVX512CD__   //conflict detection instructions

AVX512 选项 likely be in GCC, Clang, and ICC soon (if not already) :

-mavx512bw    __AVX512BW__   //byte and word instructions
-mavx512dq    __AVX512DQ__   //doubleword and quadword Instructions
-mavx512vl    __AVX512VL__   //vector length extensions

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

我不是 100% 了解 AVX512 的 ICC 编译器选项是什么。它可以是 -xMIC-AVX512 而不是 -mavx512f

MSVC only appears to define __AVX__ and __AVX2__ .

在您的情况下,您的代码似乎只使用 SSE2,因此如果您在 64 位模式下编译(这是 64 位用户空间中的默认模式或明确使用 -m64),则 __SSE2__ 已定义。但由于您使用了 -msse4a,因此 __SSE4A__ 也将被定义。

请注意,启用指令与确定指令集是否可用不同。如果您希望您的代码适用于多个指令集,那么 I suggest a CPU dispatcher .

关于c++ - 确定什么内在标志被激活,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27219966/

相关文章:

c++ - 什么是 undefined reference /未解析的外部符号错误,我该如何解决?

C++ - 带有链表的堆栈 - 内存错误?

c - gcc 正在工作,但没有产生可执行文件

c++ - 为什么 sqrt() 在没有为 int 定义的 int 变量上工作正常?

c - SSE int vs. float 练习

c++ - 在 X87 和 SSE FPU 中用户定义的点后截断 float 和 double

c++ - 初始化 std::pair<double, std::array<std::pair<double, double>, 3>>

c++ - OpenCv 3.3 Cuda Medianfilter 生成 2/3 的图像黑色

c++ - 带重定位但不带 PIC 的可执行文件中共享库的引用函数

assembly - FASM 对齐 32 部分对齐不够