在详细说明之前,我有以下功能,
设_e,_w是一个大小相等的数组。设_stepSize是浮点类型。
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。
答案 0 :(得分:3)
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__
AVX512选项,在最近版本的GCC,Clang和ICC中定义
-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。
对于AVX512的ICC编译器选项,我不是100%。它可以是-xMIC-AVX512
而不是-mavx512f
。
MSVC only appears to define __AVX__ and __AVX2__
在您的情况下,您的代码似乎只使用SSE2,因此如果您在64位模式下编译(这是64位用户空间中的默认模式或使用-m64
显式编译),那么__SSE2__
被定义为。但是,由于您使用了-msse4a
,因此也会定义__SSE4A__
。
请注意,启用指令与确定指令集是否可用不同。如果您希望代码在多个指令集上工作,那么I suggest a CPU dispatcher。
答案 1 :(得分:0)
我后来才知道没有办法做到这一点。这是一个简单而优雅的方式。对于带有sse4a内在函数的x86-64平台,请执行以下命令make-rule(假设您在build / *中的src / intrinsic /和build( .o文件)中存储内部源代码): p>
CXX=g++ -O3
CXXFLAGS=-std=c++14 -Wunused
CPPFLAGS=
CPP_INTRINSIC_FLAG:=-ffast-math
INTRINSIC_OBJECT := $(patsubst src/intrinsic/%.cpp,build/%.o,$(wildcard src/intrinsic/*.cpp))
x86-64-sse4: $(eval CPP_INTRINSIC_FLAG+=-msse4a -DSSE4A) $(INTRINSIC_OBJECT)
# Intrinsic objects
build/%.o: src/intrinsic/%.cpp
$(CXX) $(CXXFLAGS) -c $(CPPFLAGS) $(CPP_INTRINSIC_FLAG) $(INCLUDE_PATHS) $^ -o $@