Skip to content

Commit

Permalink
BLD: added libflame as a useable lapack library
Browse files Browse the repository at this point in the history
Now libflame may be used as a LAPACK back-end.
libflame requires an external BLAS so one has to
also have this enabled.
Also added release notes for NPY_*_ORDER and libFLAME.
  • Loading branch information
zerothi committed May 7, 2019
1 parent 4b6b29a commit a2fa178
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 4 deletions.
32 changes: 32 additions & 0 deletions doc/release/1.17.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,38 @@ C API changes
New Features
============

libFLAME
--------
Support for building NumPy with the libFLAME linear algebra package as the LAPACK,
implementation, see
`libFLAME <https://www.cs.utexas.edu/~flame/web/libFLAME.html>`_ for details.

User-defined BLAS detection order
---------------------------------
``numpy.distutils`` now uses an environment variable, comma-separated and case
insensitive, to determine the detection order for BLAS libraries.
By default ``NPY_BLAS_ORDER=mkl,blis,openblas,atlas,accelerate,blas``.
However, to force the use of OpenBLAS simply do::

NPY_BLAS_ORDER=openblas python setup.py build

which forces the use of OpenBLAS.
This may be helpful for users which have a MKL installation but wishes to try
out different implementations.

User-defined LAPACK detection order
-----------------------------------
``numpy.distutils`` now uses an environment variable, comma-separated and case
insensitive, to determine the detection order for LAPAK libraries.
By default ``NPY_BLAS_ORDER=mkl,openblas,flame,atlas,accelerate,lapack``.
However, to force the use of OpenBLAS simply do::

NPY_LAPACK_ORDER=openblas python setup.py build

which forces the use of OpenBLAS.
This may be helpful for users which have a MKL installation but wishes to try
out different implementations.

``np.ufunc.reduce`` and related functions now accept a ``where`` mask
---------------------------------------------------------------------
``np.ufunc.reduce``, ``np.sum``, ``np.prod``, ``np.min``, ``np.max`` all
Expand Down
7 changes: 4 additions & 3 deletions doc/source/user/building.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,10 @@ The default order for the libraries are:

1. MKL
2. OpenBLAS
3. ATLAS
4. Accelerate (MacOS)
5. LAPACK (NetLIB)
3. libFLAME
4. ATLAS
5. Accelerate (MacOS)
6. LAPACK (NetLIB)


If you wish to build against OpenBLAS but you also have MKL available one
Expand Down
97 changes: 96 additions & 1 deletion numpy/distutils/system_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
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
Expand Down Expand Up @@ -388,6 +389,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
Expand Down Expand Up @@ -463,6 +465,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.
Expand Down Expand Up @@ -1590,7 +1599,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')
Expand All @@ -1610,6 +1619,13 @@ def _calc_info_openblas(self):
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:
Expand Down Expand Up @@ -2042,6 +2058,85 @@ def calc_info(self):
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', [])
if sys.version_info < (3, 5) and sys.version_info > (3, 0) and c.compiler_type == "msvc":
extra_args.append("/MANIFEST")
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)
return False

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']
Expand Down
16 changes: 16 additions & 0 deletions site.cfg.example
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,22 @@
# include_dirs = /home/username/blis/include/blis
# runtime_library_dirs = /home/username/blis/lib

# libFLAME
# --------
# libFLAME (https://www.cs.utexas.edu/~flame/web/libFLAME.html) provides a
# LAPACK interface. It's a relatively new library, its performance in some
# cases seems to match that of MKL and OpenBLAS.
# It hasn't been benchmarked with NumPy or SciPy yet.
#
# Notes on compiling libFLAME itself:
# - the LAPACK interface (needed by NumPy) isn't built by default; please
# configure with ``./configure --enable-lapack2flame``.
#
# [flame]
# libraries = flame
# library_dirs = /home/username/flame/lib
# runtime_library_dirs = /home/username/flame/lib

# MKL
#----
# Intel MKL is Intel's very optimized yet proprietary implementation of BLAS and
Expand Down

0 comments on commit a2fa178

Please sign in to comment.