Skip to content

Lapack #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 23 additions & 110 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,124 +1,37 @@
blas
BLAS
=====
This project, funded by the [Erlang Ecosystem Foundation](https://erlef.org/), was made possible thanks to [Peerst Stritzinger](https://www.stritzinger.com/)
and aims to bring the efficiency of the BLAS-LAPACKE library to Erlang.

This project is a NIF based wrapper of the Basic Linear Algebra Subprograms, which provides algorithms fine-tuned for a large variety of hardware.
This implementation uses [openblas](https://github.com/xianyi/OpenBLAS). Other cblas/lapacke implementations can be used, but will need modifictations of c_src/Makefile linking options and c_src/eblas.h include options.

This implementation uses [openblas](https://github.com/xianyi/OpenBLAS). Other cblas implementations can be used, but will need modifictations of c_src/Makefile linking options and c_src/eblas.h include options.
GRISP is supported, and uses the default [netlib](https://netlib.org) implementation.

API
----
The following sites provide a clear BLAS API:
- [netlib's](https://netlib.org/blas/) concise reference.
- [intel's](https://www.intel.com/content/www/us/en/content-details/671183/developer-reference-for-intel-math-kernel-library-intel-mkl-11-3-c.html?wapkw=BLAS%20mlk) complete reference.
- [IBM's](https://www.ibm.com/docs/en) reference, with clear examples.
A library reference is provided in [docu](docu/erlang_blas_ref.pdf).

Usage
-----
```erlang
blas:run(Tuple); % Execute on dirty scheduler
blas:run(Tuple, dirty); % Execute on dirty scheduler.
blas:run(Tuple, clean); % Execute on usual scheduler.
INSTALLATION
=====
Make sure you have a BLAS-LAPACK library to link to. On ubuntu:
```
Tuple contains, in sequence, a BLAS function name (represented as an atom), followed by its arguments in Erlang representation.

Examples
-----

[caxpy](https://www.ibm.com/docs/en/essl/6.1?topic=vss-saxpy-daxpy-caxpy-zaxpy-multiply-vector-by-scalar-add-vector-store-in-vector): single Complex numbers, Alpha*x Plus Y:

```erlang
Alpha = blas:ltb(c, [1,0]),
X = blas:ltb(c, [1,2, 2,3, 3,1]),
Y = blas:new(c, [1,1, 0,0, 1,2]),
ok = blas:run({caxpy, 3, Alpha, X, 1, Y, 1}),

io:format("Result: ~p~n", [blas:to_list(c, Y)]).
sudo apt-get install libopenblas-serial-dev
sudo apt-get install liblapacke-dev
```

[stpmv](https://www.ibm.com/docs/en/essl/6.1?topic=mvs-strmv-dtrmv-ctrmv-ztrmv-stpmv-dtpmv-ctpmv-ztpmv-matrix-vector-product-triangular-matrix-its-transpose-its-conjugate-transpose): Single real numbers, Triangular Packed Matrix, Matrix*Vector operation.

```erlang
N = 3,
A = blas:new(s, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]),
X = blas:new(s, [-0.25,-0.125,0.5]),
ok = blas:run(
{stpmv, blasRowMajor, blasUpper, blasNoTrans, blasNonUnit, N, A, X, 1},
clean
),
[1.0,2.0,3.0] = blas:to_list(s, X).
This project can be added as a rebar3 dependency. Either clone it to a _checkout subfolder, or add it as a dependency in your rebar.config:
```

Datatype conversion tables
-----

```
enums cblas[value] blas[value]

numbers
(const)int int
void* c_binary
const float double; binary; c_binary
const double double; binary; c_binary
const void* binary; c_binary

{deps,[blas]}.
```

For example, taking stpmv's cblas signature:

```c
void cblas_stpmv(OPENBLAS_CONST enum CBLAS_ORDER order, OPENBLAS_CONST enum CBLAS_UPLO Uplo, OPENBLAS_CONST enum CBLAS_TRANSPOSE TransA, OPENBLAS_CONST enum CBLAS_DIAG Diag,
OPENBLAS_CONST blasint N, OPENBLAS_CONST float *Ap, float *X, OPENBLAS_CONST blasint incX);
```
The arguments can be represented as such:
```erlang
% enums
Order = blasRowMajor || blasColMajor
Uplo = blasUpper || blasLower
Transa = blasNoTrans || blasTrans
Diag = blasNonUnit || blasUnit

% int
N = 3
incX = 1

% const float*
A = blas:new(s, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]); % c_binary, a mutable binary
A_2 = blas:ltb(s, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]); % binary
SAFETY
=====
BLAS-LAPACKE executes in place over unbounded arrays, making sigsev crashes possible. This erlang library checks array dimensions for BLAS functions, but not for LAPACKE, making the latter potentially unsafe.

% float*
X = blas:new(s, [-0.25,-0.125,0.5]); % c_binary
```
TESTING
=====
Basic tests cases are provided to the BLAS interface. However, LAPACKE is untested.

Creating c_binaries
-----
Since BLAS functions operate in place, c_binaries representing mutable arrays are needed. They can be created as such:
```erlang
C_binary = blas:new(Binary).
% Binary is an erlang binary.
C_binary = blas:new(Type, List).
% List is a list of numbers.
% Type is used to encode the binary, and is one of:
% s -> single precision
% d -> double precision
% c -> single complex numbers: List is of even size
% Z -> double complex numbers: List is of even size
```
FUTURE WORK
====
Netlib's implementation of LAPACKE is provided with a test suite written in fortran. To use it, a [fortran interpreter]() was started, but could not be finished due to a lack of time. Another option tested was to write rewrite all LAPACKE function to pipe their arguments to an Erlang application which would execute them, and pipe the result back: [piper](https://github.com/tanguyl/piper). However, dealing with unbounded arrays proved harder than expected, piper could not be finished either. The latter option should be faster to finish, but a fortran interpreter for numerical computations could be a great tool to use existing fortran libraries.

Reading c_binaries
-----
The content of c_binaries can be retrieved as either a list of elements, or a constant binary.
Retrieving a list is done as such:
```erlang
C_binary = blas:to_list(Type, C_binary).
% Binary is a c_binary created using blas:new.
% Type is used to decode the binary, and is one of:
% s -> single precision
% d -> double precision
% c -> single complex numbers (equivalent to s)
% Z -> double complex numbers (equivqlent to d)
```
Retrieving a binary is done as such:
```erlang
Binary = blas:to_bin(C_binary).
% Binary is a c_binary created using blas:new.
```
Also, LAPACKE uses BLAS to perform its iterations. Using it in nifs present no advantages, and makes scheduling hard. Rewriting it in Erlang using a transpiler based upon the aforementioned fortran interpreter could solve this issue.
4 changes: 2 additions & 2 deletions c_src/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Source: https://github.com/dgud/blas/blob/master/c_src/Makefile

C_SRC_OUTPUT = ../priv/eblas.so
C_SRC_OUTPUT = ../priv/eblas_nif.so

ERL_INCLUDE_DIR = $(ERLANG_ROOT_DIR)/usr/include

Expand All @@ -18,7 +18,7 @@ endif

$(C_SRC_OUTPUT): *.c
$(CC) $(CFLAGS) *.c -g -fPIC -shared -o $(C_SRC_OUTPUT) -I $(ERL_INCLUDE_DIR) \
$(C_SRC_OPTS) -L/usr/lib -lopenblas
$(C_SRC_OPTS) -L/usr/lib -lopenblas -llapacke

clean:
rm -f $(C_SRC_OUTPUT)
Expand Down
Loading