From Fedora Project Wiki
(Note that we need proper sonames)
No edit summary
 
(11 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{Draft}}
{{Draft}}
= Introduction =


Besides being implementations, BLAS and LAPACK are also API standards for basic linear algebra operations (such as vector and matrix multiplication).
= Linear Algebra Libraries =


Many implementations of these API exist. The reference implementation of BLAS and LAPACK from netlib is very stable but is not as fast as optimized ones such as ATLAS and OpenBLAS.
== Introduction ==


Implementations of BLAS:
BLAS (Basic Linear Algebra Subprograms) and LAPACK (Linear Algebra PACKage) are routines that provide standard building blocks for performing a wide range of linear algebra operations operations. There are stable reference implementations from [https://netlib.org/ Netlib] written in Fortran, with C intefaces available (called CBLAS and LAPACKE respectively), as well as several optimized implementations providing fast subsets of these APIs.


*    blas - Reference implementation from netlib
=== Implementations available ===
*    atlas - Automatically Tuned Linear Algebra Software
*    openblas - OpenBLAS, an optimized BLAS based on GotoBLAS2


Implementations of LAPACK:
* `blas`, `lapack` - Netlib's reference implementation of the Fortran and C interfaces.
* `atlas` - Automatically Tuned Linear Algebra Software.
* `blis` - BLAS-like Library Instantiation Software framework.
* `openblas` - OpenBLAS, an optimized BLAS based on GotoBLAS2.


*  lapack - Reference implementation from netlib
*  ATLAS and OpenBLAS both provide an optimized subset of LAPACK


Due to implementation differences, it is important that all components of a particular software stack link to the same BLAS/LAPACK implementation. Also, users may want to choose a particular implementation that works best for them at run time.  This guideline gives a structure that can enforce the first while allowing the second.
ATLAS, BLIS and OpenBLAS provide BLAS and a subset of LAPACK. Both BLIS and OpenBLAS provide several flavors: a sequential version, a threaded one, and another with OpenMP support (all of them with or without support for 64-bit integers).


= BLAS/LAPACK implementations =
Due to implementation differences, it is important that all components of a particular software stack link to the same BLAS/LAPACK implementation. Also, users may want to choose a particular implementation that works best for them at run time.  This guideline gives a structure that can enforce the first while allowing the second, as well as providing a transparent fallback mechanism to Netlib's reference implementation for those symbols not included in the selected backend via [https://www.mpi-magdeburg.mpg.de/projects/flexiblas FlexiBLAS].


Implementations of a BLAS and/or LAPACK library must build versions of their libraries with the libblas.so.3 and liblapack.so3 sonames containing the appropriate symbols and ship them in %{_libdir}/IMPLEMENTATION-NAME/.  Each implementation may have multiple IMPLEMENTATION-NAMEs, e.g. for serial and parallel versions.
=== BLAS/LAPACK wrapper ===


For example, atlas would have:
[https://www.mpi-magdeburg.mpg.de/projects/flexiblas FlexiBLAS] is a framework that wraps both BLAS and LAPACK APIs in a single library. BLAS/LAPACK consumers must link against FlexiBLAS, and this wrapper is able to redirect calls to a selected optimized backend with negligible overhead. It also provides transparent fallback to Netlib's reference implementation if a certain symbol is not present in the selected backend. These are the main features:


%files
* Provides a 100% BLAS and LAPACK compatible ABI/API, with interfaces for both 32- and 64-bit integers.
...
* Runtime exchangeable BLAS and LAPACK backend without recompilation via an environment variable.
%{_libdir}/%{name}-serial/libblas.so.3
* Integration of user-owned BLAS libraries without administrator privileges, even in system-wide installed programs.
%{_libdir}/%{name}-serial/liblapack.so.3
* Works with OpenBLAS, ATLAS and BLIS, as well as non-free alternatives such as Intel MKL, ACML...
%{_libdir}/%{name}-threaded/libblas.so.3
* Flexible per-system/user/host configuration files.
%{_libdir}/%{name}-threaded/liblapack.so.3
* Basic profiling support.


If ILP64 (64-bit integer) implementations are available, they should be provided as well.  For openblas:


%files
Fedora ships `openblas-openmp` as the system-wide default backend.
...
%{_libdir}/%[name}-serial/libblas64.so.3
%{_libdir}/%{name}-serial/liblapack64.so.3
%{_libdir}/%{name}-serial/libblas64_.so.3
%{_libdir}/%{name}-serial/liblapack64_.so.3


== System level BLAS/LAPACK selection ==
== Packaging BLAS/LAPACK dependent packages ==


To allow system level selection of the desired BLAS/LAPACK implementation, alternatives are used, selecting which path is desired for /etc/ld.so.conf.d/blas-%{arch}.conf.
Consumers of any subset of BLAS and/or LAPACK MUST compile against FlexiBLAS (unless this is not supported; see [[Exceptions]] below).


<pre>
=== Build requirements ===
Requires(post): %{_sbindir}/update-alternatives
Requires(postun): %{_sbindir}/update-alternatives


%install
First, only FlexiBLAS's development package MUST be listed in `BuildRequires`:
...
mkdir -p %{buildroot}%{_sysconfdir}/ld.so.conf.d
touch %{buildroot}%{_sysconfdir}/ld.so.conf.d/blas-%{_arch}.conf
echo %{_libdir}/%{name}-serial > %{buildroot}%{_sysconfdir}/ld.so.conf.d/blas-%{_arch}.conf-%{name}-serial


%post
BuildRequires: flexiblas-devel
%{_sbindir}/update-alternatives --install %{_sysconfdir}/ld.so.conf.d/blas-%{_arch}.conf \
  blas %{_sysconfdir}/ld.so.conf.d/blas-%{_arch}.conf-%{name}-serial 60
/sbin/ldconfig


%postun
Alternatively, packages using `pkg-config` SHOULD express this dependency as
if [ $1 -eq 0 ] ; then
  %{_sbindir}/update-alternatives --remove blas %{_sysconfdir}/ld.so.conf.d/blas-%{_arch}.conf-%{name}-serial
fi
/sbin/ldconfig
</pre>


Current established priorities are 30 for atlas and 60 for openblas.
BuildRequires: pkgconfig(flexiblas)


Also, we provide libblas/liblapack:
if the package requires the 32-bit interface (this is the most common case), or a conditional `BuildRequires` such as


  %if %{_lib} == "lib64"
  %if 0%{?__isa_bits} == 64
  Provides: libblas.so.3()(64bit)
  BuildRequires: pkgconfig(flexiblas64)
Provides: liblapack.so.3()(64bit)
  %else
  %else
  Provides: libblas.so.3
  BuildRequires: pkgconfig(flexiblas)
Provides: liblapack.so.3
  %endif
  %endif


== User level BLAS/LAPACK selection ==
if the package uses the 64-bit interface when available. However, note that if the package '''only''' supports this 64-bit interface, then 32-bit architectures MUST be excluded.


Environment modules are used to provide user level selection of the desired BLAS/LAPACK implementation.  For each IMPLEMENTATION-NAME, the implementation package will provide an environment module, e.g.:
=== Configuration ===


#%Module 1.0
Packages using `pkg-config` will automatically obtain the proper paths to the headers and libraries. Similarly, CMake-based projects using `FindBLAS` will automatically detect and configure the proper flags for FlexiBLAS (since CMake v3.19), and no further action will be required from the packager.
# ATLAS module for loading serial atlas library
conflict                blas
prepend-path            LD_LIBRARY_PATH /usr/lib64/atlas-serial


as %{_datadir}/modulefiles/blas/atlas-serial. The implementation must then require an environment module implementation:
Unfortunately, many upstream projects present heterogeneous ways of accessing these APIs. In a best-case scenario, the building framework may define specific options to explicitly set the BLAS and/or LAPACK libraries. More commonly, the packager MUST ensure that `%{_includedir}/flexiblas` and `%{_libdir}/flexiblas` are injected as header and library locations in the proper flags and configuration files. In rare occasions, hardcoded paths in source files MUST be modified, and patches MAY be required. The packager SHOULD work with upstream to standardize the way in which these libraries are detected and configured.


Requires: environment(modules)
To ensure that the program has been properly linked against FlexiBLAS, the packager MUST check that the `Requires` are correct, i.e., `libflexiblas` is listed, but not `libblas`, `liblapack` or any other backend.


Because many (all except the reference?) BLAS/LAPACK implementations are combined BLAS/LAPACK libraries, we do not support separate specification of BLAS and LAPACK, only combinations that are explicitly known to work.
=== Tests ===


== Consistent LAPACK versions ==
Optimized BLAS/LAPACK backends are much faster than Netlib's reference implementation, but in return results may vary a little. Consequently, tests that are too tight (with too small tolerances) may fail. In these cases, the packager SHOULD enable the reference implementation in the `%check` section as follows:


Most optimized BLAS implementations also offer a subset of optimized LAPACK functions.  They must then fill out the rest of the LAPACK API from the reference netlib LAPACK, either via static LAPACK library or a bundled version.  The reference LAPACK interface is slowly changing so it is important that the LAPACK API version be consistent across all LAPCK implementations on a specific release.  This is most easily handled by linking to the static LAPACK reference library.
  export FLEXIBLAS=netlib


= BLAS/LAPACK dependent packages =
or, alternatively, via `FLEXIBLAS64` for builds using 64-bit integers.


== Generic Usage ==
=== Exceptions ===
If the BLAS/LAPACK consumer does not require special compile time configuration for different BLAS/LAPACK implementations, it should simply build against the reference implementation:


BuildRequires: blas-devel
* Although support for LAPACKE is planned, the few packages using this interface are not yet supported by FlexiBLAS as of v3.1.2. These packages MUST link against OpenBLAS instead, or `lapack` if the routines used are not supported by this backend. Current exceptions of this type include `opencv`, `scamp` and `sextractor`.
BuildRequires: lapack-devel


so that they end up linking to libblas.so.3 and liblapack.so.3, thus allowing the implementation to be switched at run time.
* On rare occasions, a package may use an exceptional feature present in a particular backend and cannot be adapted to FlexiBLAS by any means. In such cases, the package MUST link against this backend. Current exceptions of this type include `julia` (linked against OpenBLAS) and `psfex` (linked against ATLAS).


== Compile time configuration ==
== Backend selection ==


If the consumer requires special configuration for different implementations, it should provide versions compiled with each implementation.
=== System-level selection ===


= End-User Documentation =
A package compiled against FlexiBLAS pulls out the corresponding `flexiblas-netlib(64)` subpackage, which in turn requires the default optimized backend (i.e., `flexiblas-openblas-openmp(64)`). This is set via the "default=IMPLEMENTATION-NAME" key (by default, `default=openblas-openmp`), present in the main configuration file shipped in the main subpackages, `%{_sysconfdir}/flexiblasrc` and `%{_sysconfdir}/flexiblas64rc`.


End users will load the implementation they desire with:
To allow system-level selection of other BLAS/LAPACK implementations, more backends must be installed in the first place (e.g., flexiblas-atlas, flexiblas-blis-serial...), and then they can be swapped system-wide via the `flexiblas` CLI tool, or just by modifying the "default" key in the configuration file by hand.


module load blas/IMPLEMENTATION-NAME
=== User-level selection ===


TODO - choose a distribution default?
Persistent user-level selection of system-provided BLAS/LAPACK implementations can be done via the CLI tool:


$ flexiblas set IMPLEMENTATION-NAME
$ flexiblas64 set IMPLEMENTATION-NAME
provided the sub-package for `IMPLEMENTATION-NAME` is installed.
Non-persistent user-level selection can be triggered via an environment variable:
$ FLEXIBLAS=IMPLEMENTATION-NAME ./yourapp
$ FLEXIBLAS64=IMPLEMENTATION-NAME ./yourapp64
User-level selection of user-owned BLAS/LAPACK libraries can be achieved just by changing `IMPLEMENTATION-NAME` with a path to any custom BLAS/LAPACK-compatible library in the examples above.


[[Category:Packaging guidelines drafts]]
[[Category:Packaging guidelines drafts]]

Latest revision as of 17:31, 18 January 2022

This page is a draft only
It is still under construction and content may change. Do not rely on the information on this page.

Linear Algebra Libraries

Introduction

BLAS (Basic Linear Algebra Subprograms) and LAPACK (Linear Algebra PACKage) are routines that provide standard building blocks for performing a wide range of linear algebra operations operations. There are stable reference implementations from Netlib written in Fortran, with C intefaces available (called CBLAS and LAPACKE respectively), as well as several optimized implementations providing fast subsets of these APIs.

Implementations available

  • blas, lapack - Netlib's reference implementation of the Fortran and C interfaces.
  • atlas - Automatically Tuned Linear Algebra Software.
  • blis - BLAS-like Library Instantiation Software framework.
  • openblas - OpenBLAS, an optimized BLAS based on GotoBLAS2.


ATLAS, BLIS and OpenBLAS provide BLAS and a subset of LAPACK. Both BLIS and OpenBLAS provide several flavors: a sequential version, a threaded one, and another with OpenMP support (all of them with or without support for 64-bit integers).

Due to implementation differences, it is important that all components of a particular software stack link to the same BLAS/LAPACK implementation. Also, users may want to choose a particular implementation that works best for them at run time. This guideline gives a structure that can enforce the first while allowing the second, as well as providing a transparent fallback mechanism to Netlib's reference implementation for those symbols not included in the selected backend via FlexiBLAS.

BLAS/LAPACK wrapper

FlexiBLAS is a framework that wraps both BLAS and LAPACK APIs in a single library. BLAS/LAPACK consumers must link against FlexiBLAS, and this wrapper is able to redirect calls to a selected optimized backend with negligible overhead. It also provides transparent fallback to Netlib's reference implementation if a certain symbol is not present in the selected backend. These are the main features:

  • Provides a 100% BLAS and LAPACK compatible ABI/API, with interfaces for both 32- and 64-bit integers.
  • Runtime exchangeable BLAS and LAPACK backend without recompilation via an environment variable.
  • Integration of user-owned BLAS libraries without administrator privileges, even in system-wide installed programs.
  • Works with OpenBLAS, ATLAS and BLIS, as well as non-free alternatives such as Intel MKL, ACML...
  • Flexible per-system/user/host configuration files.
  • Basic profiling support.


Fedora ships openblas-openmp as the system-wide default backend.

Packaging BLAS/LAPACK dependent packages

Consumers of any subset of BLAS and/or LAPACK MUST compile against FlexiBLAS (unless this is not supported; see Exceptions below).

Build requirements

First, only FlexiBLAS's development package MUST be listed in BuildRequires:

BuildRequires: flexiblas-devel

Alternatively, packages using pkg-config SHOULD express this dependency as

BuildRequires: pkgconfig(flexiblas)

if the package requires the 32-bit interface (this is the most common case), or a conditional BuildRequires such as

%if 0%{?__isa_bits} == 64
BuildRequires: pkgconfig(flexiblas64)
%else
BuildRequires: pkgconfig(flexiblas)
%endif

if the package uses the 64-bit interface when available. However, note that if the package only supports this 64-bit interface, then 32-bit architectures MUST be excluded.

Configuration

Packages using pkg-config will automatically obtain the proper paths to the headers and libraries. Similarly, CMake-based projects using FindBLAS will automatically detect and configure the proper flags for FlexiBLAS (since CMake v3.19), and no further action will be required from the packager.

Unfortunately, many upstream projects present heterogeneous ways of accessing these APIs. In a best-case scenario, the building framework may define specific options to explicitly set the BLAS and/or LAPACK libraries. More commonly, the packager MUST ensure that %{_includedir}/flexiblas and %{_libdir}/flexiblas are injected as header and library locations in the proper flags and configuration files. In rare occasions, hardcoded paths in source files MUST be modified, and patches MAY be required. The packager SHOULD work with upstream to standardize the way in which these libraries are detected and configured.

To ensure that the program has been properly linked against FlexiBLAS, the packager MUST check that the Requires are correct, i.e., libflexiblas is listed, but not libblas, liblapack or any other backend.

Tests

Optimized BLAS/LAPACK backends are much faster than Netlib's reference implementation, but in return results may vary a little. Consequently, tests that are too tight (with too small tolerances) may fail. In these cases, the packager SHOULD enable the reference implementation in the %check section as follows:

 export FLEXIBLAS=netlib

or, alternatively, via FLEXIBLAS64 for builds using 64-bit integers.

Exceptions

  • Although support for LAPACKE is planned, the few packages using this interface are not yet supported by FlexiBLAS as of v3.1.2. These packages MUST link against OpenBLAS instead, or lapack if the routines used are not supported by this backend. Current exceptions of this type include opencv, scamp and sextractor.
  • On rare occasions, a package may use an exceptional feature present in a particular backend and cannot be adapted to FlexiBLAS by any means. In such cases, the package MUST link against this backend. Current exceptions of this type include julia (linked against OpenBLAS) and psfex (linked against ATLAS).

Backend selection

System-level selection

A package compiled against FlexiBLAS pulls out the corresponding flexiblas-netlib(64) subpackage, which in turn requires the default optimized backend (i.e., flexiblas-openblas-openmp(64)). This is set via the "default=IMPLEMENTATION-NAME" key (by default, default=openblas-openmp), present in the main configuration file shipped in the main subpackages, %{_sysconfdir}/flexiblasrc and %{_sysconfdir}/flexiblas64rc.

To allow system-level selection of other BLAS/LAPACK implementations, more backends must be installed in the first place (e.g., flexiblas-atlas, flexiblas-blis-serial...), and then they can be swapped system-wide via the flexiblas CLI tool, or just by modifying the "default" key in the configuration file by hand.

User-level selection

Persistent user-level selection of system-provided BLAS/LAPACK implementations can be done via the CLI tool:

$ flexiblas set IMPLEMENTATION-NAME
$ flexiblas64 set IMPLEMENTATION-NAME

provided the sub-package for IMPLEMENTATION-NAME is installed.

Non-persistent user-level selection can be triggered via an environment variable:

$ FLEXIBLAS=IMPLEMENTATION-NAME ./yourapp
$ FLEXIBLAS64=IMPLEMENTATION-NAME ./yourapp64

User-level selection of user-owned BLAS/LAPACK libraries can be achieved just by changing IMPLEMENTATION-NAME with a path to any custom BLAS/LAPACK-compatible library in the examples above.