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。
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 调度程序。