summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/code_generators/generate_umath.py4
-rw-r--r--numpy/core/include/numpy/npy_common.h16
-rw-r--r--numpy/core/setup.py1
-rw-r--r--numpy/core/setup_common.py1
-rw-r--r--numpy/core/src/umath/cpuid.c56
-rw-r--r--numpy/core/src/umath/cpuid.h9
6 files changed, 69 insertions, 18 deletions
diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py
index ebcf864ea..1d3550e06 100644
--- a/numpy/core/code_generators/generate_umath.py
+++ b/numpy/core/code_generators/generate_umath.py
@@ -966,7 +966,7 @@ def make_arrays(funcdict):
for vt in t.simd:
code2list.append(textwrap.dedent("""\
#ifdef HAVE_ATTRIBUTE_TARGET_{ISA}
- if (NPY_CPU_SUPPORTS_{ISA}) {{
+ if (npy_cpu_supports("{ISA}")) {{
{fname}_functions[{idx}] = {type}_{fname}_{isa};
}}
#endif
@@ -1073,7 +1073,7 @@ def make_code(funcdict, filename):
Please make changes to the code generator program (%s)
**/
-
+ #include "cpuid.h"
%s
static int
diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h
index b7634a930..5faff4385 100644
--- a/numpy/core/include/numpy/npy_common.h
+++ b/numpy/core/include/numpy/npy_common.h
@@ -101,22 +101,6 @@
#endif
#endif
-#ifdef HAVE___BUILTIN_CPU_SUPPORTS
- #ifdef HAVE_ATTRIBUTE_TARGET_AVX2
- #define NPY_CPU_SUPPORTS_AVX2 __builtin_cpu_supports("avx2")
- #else
- #define NPY_CPU_SUPPORTS_AVX2 0
- #endif
- #ifdef HAVE_ATTRIBUTE_TARGET_AVX
- #define NPY_CPU_SUPPORTS_AVX __builtin_cpu_supports("avx")
- #else
- #define NPY_CPU_SUPPORTS_AVX 0
- #endif
-#else
- #define NPY_CPU_SUPPORTS_AVX 0
- #define NPY_CPU_SUPPORTS_AVX2 0
-#endif
-
#if defined(_MSC_VER)
#define NPY_INLINE __inline
#elif defined(__GNUC__)
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index d519e0eb8..15f6e1522 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -888,6 +888,7 @@ def configuration(parent_package='',top_path=None):
join('src', 'umath', 'loops.c.src'),
join('src', 'umath', 'ufunc_object.c'),
join('src', 'umath', 'extobj.c'),
+ join('src', 'umath', 'cpuid.c'),
join('src', 'umath', 'scalarmath.c.src'),
join('src', 'umath', 'ufunc_type_resolution.c'),
join('src', 'umath', 'override.c'),
diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py
index 1fe953910..f36d61f55 100644
--- a/numpy/core/setup_common.py
+++ b/numpy/core/setup_common.py
@@ -146,6 +146,7 @@ OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'),
"stdio.h", "LINK_AVX"),
("__asm__ volatile", '"vpand %ymm1, %ymm2, %ymm3"',
"stdio.h", "LINK_AVX2"),
+ ("__asm__ volatile", '"xgetbv"', "stdio.h", "XGETBV"),
]
# function attributes
diff --git a/numpy/core/src/umath/cpuid.c b/numpy/core/src/umath/cpuid.c
new file mode 100644
index 000000000..912d51eeb
--- /dev/null
+++ b/numpy/core/src/umath/cpuid.c
@@ -0,0 +1,56 @@
+#define _UMATHMODULE
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+
+#include <Python.h>
+
+#include "npy_config.h"
+
+#define PY_ARRAY_UNIQUE_SYMBOL _npy_umathmodule_ARRAY_API
+#define NO_IMPORT_ARRAY
+
+#include "cpuid.h"
+
+#define XCR_XFEATURE_ENABLED_MASK 0x0
+#define XSTATE_SSE 0x2
+#define XSTATE_YMM 0x4
+
+/*
+ * verify the OS supports avx instructions
+ * it can be disabled in some OS, e.g. with the nosavex boot option of linux
+ */
+static NPY_INLINE
+int os_avx_support(void)
+{
+#if HAVE_XGETBV
+ /*
+ * use bytes for xgetbv to avoid issues with compiler not knowing the
+ * instruction
+ */
+ unsigned int eax, edx;
+ unsigned int ecx = XCR_XFEATURE_ENABLED_MASK;
+ __asm__("xgetbv" : "=a" (eax), "=d" (edx) : "c" (ecx));
+ return (eax & (XSTATE_SSE | XSTATE_YMM)) == (XSTATE_SSE | XSTATE_YMM);
+#else
+ return 0;
+#endif
+}
+
+
+/*
+ * Primitive cpu feature detect function
+ * Currently only supports checking for avx on gcc compatible compilers.
+ */
+NPY_NO_EXPORT int
+npy_cpu_supports(const char * feature)
+{
+#ifdef HAVE___BUILTIN_CPU_SUPPORTS
+ if (strcmp(feature, "avx2") == 0) {
+ return __builtin_cpu_supports("avx2") && os_avx_support();
+ }
+ else if (strcmp(feature, "avx") == 0) {
+ return __builtin_cpu_supports("avx") && os_avx_support();
+ }
+#endif
+
+ return 0;
+}
diff --git a/numpy/core/src/umath/cpuid.h b/numpy/core/src/umath/cpuid.h
new file mode 100644
index 000000000..33702ed41
--- /dev/null
+++ b/numpy/core/src/umath/cpuid.h
@@ -0,0 +1,9 @@
+#ifndef _NPY_PRIVATE__CPUID_H_
+#define _NPY_PRIVATE__CPUID_H_
+
+#include <numpy/ndarraytypes.h> /* for NPY_NO_EXPORT */
+
+NPY_NO_EXPORT int
+npy_cpu_supports(const char * feature);
+
+#endif