27 #if defined(AVX) || defined(AVX2) || defined(SSE4_1) 31 #if defined(HAS_CPUID) 54 "Function used for calculation of dot product");
59 bool SIMDDetect::avx_available_;
60 bool SIMDDetect::avx2_available_;
61 bool SIMDDetect::avx512F_available_;
62 bool SIMDDetect::avx512BW_available_;
64 bool SIMDDetect::sse_available_;
67 static double DotProductGeneric(
const double* u,
const double* v,
int n) {
69 for (
int k = 0; k < n; ++k) total += u[k] * v[k];
74 static double DotProductStdInnerProduct(
const double* u,
const double* v,
int n) {
75 return std::inner_product(u, u + n, v, 0.0);
88 SIMDDetect::SIMDDetect() {
90 SetDotProduct(DotProductGeneric);
92 #if defined(HAS_CPUID) 94 unsigned int eax, ebx, ecx, edx;
95 if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) != 0) {
99 sse_available_ = (ecx & 0x00080000) != 0;
102 avx_available_ = (ecx & 0x10000000) != 0;
103 if (avx_available_) {
107 __cpuid_count(7, 0, eax, ebx, ecx, edx);
108 avx2_available_ = (ebx & 0x00000020) != 0;
109 avx512F_available_ = (ebx & 0x00010000) != 0;
110 avx512BW_available_ = (ebx & 0x40000000) != 0;
114 # elif defined(_WIN32) 118 max_function_id = cpuInfo[0];
119 if (max_function_id >= 1) {
122 sse_available_ = (cpuInfo[2] & 0x00080000) != 0;
125 avx_available_ = (cpuInfo[2] & 0x10000000) != 0;
128 if (max_function_id >= 7) {
130 avx2_available_ = (cpuInfo[1] & 0x00000020) != 0;
131 avx512F_available_ = (cpuInfo[1] & 0x00010000) != 0;
132 avx512BW_available_ = (cpuInfo[1] & 0x40000000) != 0;
137 #error "I don't know how to test for SIMD with this compiler" 145 }
else if (avx2_available_) {
150 }
else if (avx_available_) {
155 }
else if (sse_available_) {
165 const char* dotproduct_method =
"generic";
166 if (!strcmp(dotproduct.string(),
"auto")) {
168 }
else if (!strcmp(dotproduct.string(),
"generic")) {
170 SetDotProduct(DotProductGeneric);
171 dotproduct_method =
"generic";
172 }
else if (!strcmp(dotproduct.string(),
"native")) {
175 dotproduct_method =
"native";
177 }
else if (!strcmp(dotproduct.string(),
"avx2")) {
180 dotproduct_method =
"avx2";
183 }
else if (!strcmp(dotproduct.string(),
"avx")) {
186 dotproduct_method =
"avx";
189 }
else if (!strcmp(dotproduct.string(),
"sse")) {
192 dotproduct_method =
"sse";
194 }
else if (!strcmp(dotproduct.string(),
"std::inner_product")) {
196 SetDotProduct(DotProductStdInnerProduct);
197 dotproduct_method =
"std::inner_product";
200 tprintf(
"Warning, ignoring unsupported config variable value: dotproduct=%s\n",
201 dotproduct.string());
202 tprintf(
"Support values for dotproduct: auto generic native" 209 " std::inner_product.\n");
212 dotproduct.set_value(dotproduct_method);
static const IntSimdMatrix intSimdMatrixAVX2
double DotProductAVX(const double *u, const double *v, int n)
DotProductFunction DotProduct
double DotProductNative(const double *u, const double *v, int n)
#define STRING_VAR(name, val, comment)
DLLSYM void tprintf(const char *format,...)
double(*)(const double *, const double *, int) DotProductFunction
static const IntSimdMatrix intSimdMatrixSSE
double DotProductSSE(const double *u, const double *v, int n)
static TESS_API void Update()
static const IntSimdMatrix * intSimdMatrix