This is a set of Guile FFI bindings for the linear algebra subprograms library, BLIS1. It provides operations such as vector dot product, matrix-vector product, matrix-matrix product, and so on. These bindings are for BLIS' ‘typed’ API2.
To use the bindings, import (ffi blis)
. BLIS will be loaded from the
default dynamic library path (see ‘Installation notes’ below). There are up to
three bindings for each function, here using zgemm
as an example:
-
bli_zgemm
(raw binding): the raw C function bypointer->procedure
. Don't use this if you aren't familiar with Guile's FFI. These functions take numeric constants for thetrans_t
parameters, etc. which have the same names as in C (likeBLIS_TRANSPOSE
, note the underscore). -
blis-zgemm!
(typed binding): takes array arguments of type'c64
and operates by effect, without making copies. All the arguments must be properly sized. These functions take typed constants for thetrans_t
parameters, which have hyphened names (likeBLIS-TRANSPOSE
). This allowsguile-ffi-blis
to signal an error if you e.g. passBLIS-NO-CONJUGATE
for atrans_t
parameter. For convenience, this function returns the output argument. -
blis-zgemm
(functional binding): takes array arguments of compatible types and returns a newly constructed array. The arguments will be converted as necessary, which may result in copies. The returned array will be of'c64
type.
In principle, for the last two bindings, you don't need to care whether your array is row-major or column-major or what the strides are. The bindings will extract the required strides from the array arguments3.
If the function doesn't return an array (e.g. blis-cdot
) then we only provide
two bindings (e.g. bli_cdot
and blis-cdot
).
The bindings also provide type generic versions of the functions
(e.g. blis-dotv
for BLIS blis-sdotv blis-ddotv blis-cdotv blis-zdotv
). These simply call one of the typed variants according to the type
of the first array argument.
Enter ,help (ffi blis)
at the Guile REPL to list all the bindings
available4.
guile-ffi-blis
uses dynamic-link
to load the dynamic library for BLIS,
so the names of the respective library files must be known. The default name
libblis
can be configured with the environment variable
GUILE_FFI_BLIS_LIBNAME
.
If your BLIS library isn't installed in the default dynamic library search
path, you can configure specific paths for guile-ffi-blis
with the environment
variable GUILE_FFI_BLIS_LIBPATH
. There are other variables that control where
dynamic-link
searches for libraries (LTDL_LIBRARY_PATH
, LD_LIBRARY_PATH
)
and you may prefer to set those instead.
A previous version of this library also included CBLAS bindings, but now I have moved those to a
separate library (guile-ffi-cblas
). The following notes on using that previous version on Guix
might still be useful for guile-ffi-blis
:
https://notabug.org/ZelphirKaltstahl/guile-ml#using-guile-ffi-cblas.
The tests use SRFI-64.
$GUILE -L mod -s test/test-ffi-blis.scm
Depending on your installation (see above) you might need
GUILE_FFI_BLIS_LIBNAME=libotherblas \
GUILE_FFI_BLIS_LIBPATH=/custom/path/lib \
$GUILE ... etc.
setv
copyv
axpyv
axpbyv
swapv
dotv
norm1v
normfv
normiv
amaxv
setm
copym
axpym
gemv
ger
gemm
¹ See https://github.com/flame/blis and also the related https://www.netlib.org/blas/, https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms. ↩
² See https://github.com/flame/blis/blob/master/docs/BLISTypedAPI.md. ↩
³ By default (2020/07) BLIS will flag overlapping stride
combinations in any of the array arguments as errors, even when the result is
well defined (some discussion on the topic
here). However,
if you disable BLIS' internal error checking with
(blis-error-checking-level-set! BLIS_NO_ERROR_CHECKING)
BLIS will produce
the correct result, as far as I've been able to verify. (ffi blis)
performs
independent shape checks on the typed and functional bindings, and the Guile
array arguments have valid strides by construction, so the lack of error
checking by BLIS itself isn't necessarily a problem. The test suite includes
tests with a variety of overlapping stride combinations for gemm
and
gemv
. Still, BLIS doesn't officially support these strides. Note that if
the destination argument has overlapping strides, then the result depends on
the order in which the operations are carried out and is pretty much
undefined. (ffi blis)
will not check the destination argument for this
error. ↩
⁴ This triggers a bug in the current version. You can use
bli[TAB]
as a substitute. ↩