diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2021-05-04 15:31:41 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-04 15:31:41 -0600 |
commit | a59973902c6706cfc4e6958e69e9a9b33db333fb (patch) | |
tree | d6be2c2b035ee0c2ff7dc38b4dc0b8e26ed1401c /numpy | |
parent | 4d753a0cd67cc381af9d096afdafda674a37c971 (diff) | |
parent | 06fffd94729a920961648dd86a8b8e86f6c25326 (diff) | |
download | numpy-a59973902c6706cfc4e6958e69e9a9b33db333fb.tar.gz |
Merge pull request #18874 from Matthew-Badin/enable-accelerate
BLD, ENH: Enable Accelerate Framework
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/setup.py | 5 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 65 | ||||
-rw-r--r-- | numpy/distutils/system_info.py | 28 | ||||
-rw-r--r-- | numpy/linalg/setup.py | 5 |
4 files changed, 72 insertions, 31 deletions
diff --git a/numpy/core/setup.py b/numpy/core/setup.py index df405bcaf..d1229ee8f 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -405,11 +405,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 2dea5518c..1ac2abba1 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -6212,6 +6212,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. diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py index 85a0c9321..82e864a5c 100644 --- a/numpy/distutils/system_info.py +++ b/numpy/distutils/system_info.py @@ -375,22 +375,6 @@ default_src_dirs = [_m for _m in default_src_dirs if os.path.isdir(_m)] so_ext = get_shared_lib_extension() -def is_symlink_to_accelerate(filename): - accelpath = '/System/Library/Frameworks/Accelerate.framework' - return (sys.platform == 'darwin' and os.path.islink(filename) and - os.path.realpath(filename).startswith(accelpath)) - - -_accel_msg = ( - 'Found {filename}, but that file is a symbolic link to the ' - 'MacOS Accelerate framework, which is not supported by NumPy. ' - 'You must configure the build to use a different optimized library, ' - 'or disable the use of optimized BLAS and LAPACK by setting the ' - 'environment variables NPY_BLAS_ORDER="" and NPY_LAPACK_ORDER="" ' - 'before building NumPy.' -) - - def get_standard_file(fname): """Returns a list of files named 'fname' from 1) System-wide directory (directory-location of this module) @@ -539,6 +523,7 @@ def get_info(name, notfound_action=0): 'blis': blis_info, # use blas_opt instead 'lapack_mkl': lapack_mkl_info, # use lapack_opt instead 'blas_mkl': blas_mkl_info, # use blas_opt instead + 'accelerate': accelerate_info, # use blas_opt instead 'openblas64_': openblas64__info, 'openblas64__lapack': openblas64__lapack_info, 'openblas_ilp64': openblas_ilp64_info, @@ -1029,9 +1014,6 @@ class system_info: for prefix in lib_prefixes: p = self.combine_paths(lib_dir, prefix + lib + ext) if p: - # p[0] is the full path to the binary library file. - if is_symlink_to_accelerate(p[0]): - raise RuntimeError(_accel_msg.format(filename=p[0])) break if p: assert len(p) == 1 @@ -1766,8 +1748,10 @@ def get_atlas_version(**config): class lapack_opt_info(system_info): notfounderror = LapackNotFoundError + # List of all known LAPACK libraries, in the default order - lapack_order = ['mkl', 'openblas', 'flame', 'atlas', 'lapack'] + lapack_order = ['mkl', 'openblas', 'flame', + 'accelerate', 'atlas', 'lapack'] order_env_var_name = 'NPY_LAPACK_ORDER' def _calc_info_mkl(self): @@ -1942,7 +1926,9 @@ class lapack64__opt_info(lapack_ilp64_opt_info): class blas_opt_info(system_info): notfounderror = BlasNotFoundError # List of all known BLAS libraries, in the default order - blas_order = ['mkl', 'blis', 'openblas', 'atlas', 'blas'] + + blas_order = ['mkl', 'blis', 'openblas', + 'accelerate', 'atlas', 'blas'] order_env_var_name = 'NPY_BLAS_ORDER' def _calc_info_mkl(self): diff --git a/numpy/linalg/setup.py b/numpy/linalg/setup.py index 5c9f2a4cb..e2944f38c 100644 --- a/numpy/linalg/setup.py +++ b/numpy/linalg/setup.py @@ -9,11 +9,6 @@ def configuration(parent_package='', top_path=None): config.add_subpackage('tests') - # Accelerate is buggy, disallow it. See also numpy/core/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') - # Configure lapack_lite src_dir = 'lapack_lite' |