summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
authorMatthew Badin <mbadin@apple.com>2021-04-28 16:56:01 -0700
committerMatthew Badin <mbadin@apple.com>2021-04-28 17:20:11 -0700
commite28da7a3d50862fa99b8b704d60fc6543b5af631 (patch)
tree57f4c3684d5333c319d3b7a3cbcdbb087418acc4 /numpy/core
parent53e34d49d46b0999927160444a7dd0650efafad7 (diff)
downloadnumpy-e28da7a3d50862fa99b8b704d60fc6543b5af631.tar.gz
BLD: Enable Accelerate Framework
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/setup.py9
-rw-r--r--numpy/core/tests/test_multiarray.py65
2 files changed, 69 insertions, 5 deletions
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index df405bcaf..f59b67c88 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -10,6 +10,10 @@ from os.path import join
from numpy.distutils import log
from distutils.dep_util import newer
from sysconfig import get_config_var
+
+from numpy._build_utils.apple_accelerate import (
+ uses_accelerate_framework
+ )
from numpy.compat import npy_load_module
from setup_common import * # noqa: F403
@@ -405,11 +409,6 @@ def configuration(parent_package='',top_path=None):
from numpy.distutils.system_info import (get_info, blas_opt_info,
lapack_opt_info)
- # Accelerate is buggy, disallow it. See also numpy/linalg/setup.py
- for opt_order in (blas_opt_info.blas_order, lapack_opt_info.lapack_order):
- if 'accelerate' in opt_order:
- opt_order.remove('accelerate')
-
config = Configuration('core', parent_package, top_path)
local_dir = config.local_path
codegen_dir = join(local_dir, 'code_generators')
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 073433bd1..40b435f2e 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -6194,6 +6194,71 @@ class TestDot:
assert_equal(np.dot(b, a), res)
assert_equal(np.dot(b, b), res)
+ def test_accelerate_framework_sgemv_fix(self):
+
+ def aligned_array(shape, align, dtype, order='C'):
+ d = dtype(0)
+ N = np.prod(shape)
+ tmp = np.zeros(N * d.nbytes + align, dtype=np.uint8)
+ address = tmp.__array_interface__["data"][0]
+ for offset in range(align):
+ if (address + offset) % align == 0:
+ break
+ tmp = tmp[offset:offset+N*d.nbytes].view(dtype=dtype)
+ return tmp.reshape(shape, order=order)
+
+ def as_aligned(arr, align, dtype, order='C'):
+ aligned = aligned_array(arr.shape, align, dtype, order)
+ aligned[:] = arr[:]
+ return aligned
+
+ def assert_dot_close(A, X, desired):
+ assert_allclose(np.dot(A, X), desired, rtol=1e-5, atol=1e-7)
+
+ m = aligned_array(100, 15, np.float32)
+ s = aligned_array((100, 100), 15, np.float32)
+ np.dot(s, m) # this will always segfault if the bug is present
+
+ testdata = itertools.product((15,32), (10000,), (200,89), ('C','F'))
+ for align, m, n, a_order in testdata:
+ # Calculation in double precision
+ A_d = np.random.rand(m, n)
+ X_d = np.random.rand(n)
+ desired = np.dot(A_d, X_d)
+ # Calculation with aligned single precision
+ A_f = as_aligned(A_d, align, np.float32, order=a_order)
+ X_f = as_aligned(X_d, align, np.float32)
+ assert_dot_close(A_f, X_f, desired)
+ # Strided A rows
+ A_d_2 = A_d[::2]
+ desired = np.dot(A_d_2, X_d)
+ A_f_2 = A_f[::2]
+ assert_dot_close(A_f_2, X_f, desired)
+ # Strided A columns, strided X vector
+ A_d_22 = A_d_2[:, ::2]
+ X_d_2 = X_d[::2]
+ desired = np.dot(A_d_22, X_d_2)
+ A_f_22 = A_f_2[:, ::2]
+ X_f_2 = X_f[::2]
+ assert_dot_close(A_f_22, X_f_2, desired)
+ # Check the strides are as expected
+ if a_order == 'F':
+ assert_equal(A_f_22.strides, (8, 8 * m))
+ else:
+ assert_equal(A_f_22.strides, (8 * n, 8))
+ assert_equal(X_f_2.strides, (8,))
+ # Strides in A rows + cols only
+ X_f_2c = as_aligned(X_f_2, align, np.float32)
+ assert_dot_close(A_f_22, X_f_2c, desired)
+ # Strides just in A cols
+ A_d_12 = A_d[:, ::2]
+ desired = np.dot(A_d_12, X_d_2)
+ A_f_12 = A_f[:, ::2]
+ assert_dot_close(A_f_12, X_f_2c, desired)
+ # Strides in A cols and X
+ assert_dot_close(A_f_12, X_f_2, desired)
+
+
class MatmulCommon:
"""Common tests for '@' operator and numpy.matmul.