diff options
author | Ralf Gommers <ralf.gommers@gmail.com> | 2019-05-24 01:16:56 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-24 01:16:56 +0200 |
commit | 59622908ca14059b31d3b6c13ffab64a8151a39a (patch) | |
tree | 0de421cf99253fb61e80f75acb05ff274a933698 /numpy/distutils/system_info.py | |
parent | 9b89cfd2f0364151cc6a23806b2b03bc09e16035 (diff) | |
parent | ae34b5485d7e9cefbd690e2c8704eafa692efe99 (diff) | |
download | numpy-59622908ca14059b31d3b6c13ffab64a8151a39a.tar.gz |
Merge pull request #13158 from zerothi/linalg-flame
BLD: Add libflame as a LAPACK back-end
Diffstat (limited to 'numpy/distutils/system_info.py')
-rw-r--r-- | numpy/distutils/system_info.py | 94 |
1 files changed, 93 insertions, 1 deletions
diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py index 21d134c6b..ba4ad4643 100644 --- a/numpy/distutils/system_info.py +++ b/numpy/distutils/system_info.py @@ -17,6 +17,7 @@ classes are available: atlas_3_10_blas_threads_info, lapack_atlas_3_10_info lapack_atlas_3_10_threads_info + flame_info blas_info lapack_info openblas_info @@ -389,6 +390,7 @@ def get_info(name, notfound_action=0): 'atlas_3_10_blas_threads': atlas_3_10_blas_threads_info, 'lapack_atlas_3_10': lapack_atlas_3_10_info, # use lapack_opt instead 'lapack_atlas_3_10_threads': lapack_atlas_3_10_threads_info, # ditto + 'flame': flame_info, # use lapack_opt instead 'mkl': mkl_info, # openblas which may or may not have embedded lapack 'openblas': openblas_info, # use blas_opt instead @@ -464,6 +466,13 @@ class AtlasNotFoundError(NotFoundError): the ATLAS environment variable.""" +class FlameNotFoundError(NotFoundError): + """ + FLAME (http://www.cs.utexas.edu/~flame/web/) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [flame]).""" + + class LapackNotFoundError(NotFoundError): """ Lapack (http://www.netlib.org/lapack/) libraries not found. @@ -1591,7 +1600,7 @@ class lapack_opt_info(system_info): notfounderror = LapackNotFoundError # Default order of LAPACK checks - lapack_order = ['mkl', 'openblas', 'atlas', 'accelerate', 'lapack'] + lapack_order = ['mkl', 'openblas', 'flame', 'atlas', 'accelerate', 'lapack'] def _calc_info_mkl(self): info = get_info('lapack_mkl') @@ -1611,6 +1620,13 @@ class lapack_opt_info(system_info): return True return False + def _calc_info_flame(self): + info = get_info('flame') + if info: + self.set_info(**info) + return True + return False + def _calc_info_atlas(self): info = get_info('atlas_3_10_threads') if not info: @@ -2043,6 +2059,82 @@ class blis_info(blas_info): include_dirs=incl_dirs) self.set_info(**info) + +class flame_info(system_info): + """ Usage of libflame for LAPACK operations + + This requires libflame to be compiled with lapack wrappers: + + ./configure --enable-lapack2flame ... + + Be aware that libflame 5.1.0 has some missing names in the shared library, so + if you have problems, try the static flame library. + """ + section = 'flame' + _lib_names = ['flame'] + notfounderror = FlameNotFoundError + + def check_embedded_lapack(self, info): + """ libflame does not necessarily have a wrapper for fortran LAPACK, we need to check """ + c = customized_ccompiler() + + tmpdir = tempfile.mkdtemp() + s = """void zungqr_(); + int main(int argc, const char *argv[]) + { + zungqr_(); + return 0; + }""" + src = os.path.join(tmpdir, 'source.c') + out = os.path.join(tmpdir, 'a.out') + # Add the additional "extra" arguments + extra_args = info.get('extra_link_args', []) + try: + with open(src, 'wt') as f: + f.write(s) + obj = c.compile([src], output_dir=tmpdir) + try: + c.link_executable(obj, out, libraries=info['libraries'], + library_dirs=info['library_dirs'], + extra_postargs=extra_args) + return True + except distutils.ccompiler.LinkError: + return False + finally: + shutil.rmtree(tmpdir) + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + flame_libs = self.get_libs('libraries', self._lib_names) + + info = self.check_libs2(lib_dirs, flame_libs, []) + if info is None: + return + + if self.check_embedded_lapack(info): + # check if the user has supplied all information required + self.set_info(**info) + else: + # Try and get the BLAS lib to see if we can get it to work + blas_info = get_info('blas_opt') + if not blas_info: + # since we already failed once, this ain't going to work either + return + + # Now we need to merge the two dictionaries + for key in blas_info: + if isinstance(blas_info[key], list): + info[key] = info.get(key, []) + blas_info[key] + elif isinstance(blas_info[key], tuple): + info[key] = info.get(key, ()) + blas_info[key] + else: + info[key] = info.get(key, '') + blas_info[key] + + # Now check again + if self.check_embedded_lapack(info): + self.set_info(**info) + + class accelerate_info(system_info): section = 'accelerate' _lib_names = ['accelerate', 'veclib'] |