#matrix #vector #eigenvalues #decomposition

russell_openblas

Thin wrapper to some OpenBLAS routines

10 unstable releases (3 breaking)

Uses new Rust 2021

new 0.4.1 Jun 28, 2022
0.3.0 Jun 28, 2022
0.2.3 Oct 22, 2021
0.2.1 Sep 19, 2021
0.1.2 Aug 24, 2021

#210 in Math

Download history 43/week @ 2022-03-13 30/week @ 2022-03-20 14/week @ 2022-03-27 20/week @ 2022-04-03 12/week @ 2022-04-10 6/week @ 2022-04-17 34/week @ 2022-04-24 66/week @ 2022-05-01 88/week @ 2022-05-08 157/week @ 2022-05-15 50/week @ 2022-05-22 117/week @ 2022-05-29 56/week @ 2022-06-05 12/week @ 2022-06-12 29/week @ 2022-06-19 119/week @ 2022-06-26

228 downloads per month
Used in 7 crates (2 directly)

MIT license

165KB
3.5K SLoC

Russell OpenBLAS - Thin wrapper to some OpenBLAS routines

Crates.io

This crate is part of Russell - Rust Scientific Library

This package implements a thin wrapper to a few of the OpenBLAS routines for performing linear algebra computations.

Documentation:

Installation

Install some libraries:

sudo apt-get install \
    liblapacke-dev \
    libopenblas-dev

Add this to your Cargo.toml (choose the right version):

[dependencies]
russell_openblas = "*"

Number of threads

By default OpenBLAS will use all available threads, including Hyper-Threads that make the performance worse. Thus, it is best to set the following environment variable:

export OPENBLAS_NUM_THREADS=<real-core-count>

Furthermore, if working on a multi-threaded application, it is recommended to set:

export OPENBLAS_NUM_THREADS=1

Examples

Vector operations

use russell_openblas::{dcopy, ddot};

fn main() {
    // ddot
    let u = [1.0, 2.0, 3.0, 4.0];
    let v = [4.0, 3.0, 2.0, 1.0];
    assert_eq!(ddot(4, &u, 1, &v, 1), 20.0);

    // dcopy
    let mut w = vec![0.0; 4];
    dcopy(4, &u, 1, &mut w, 1);
    assert_eq!(w, &[1.0, 2.0, 3.0, 4.0]);
}

Matrix multiplication

use russell_chk::assert_vec_approx_eq;
use russell_openblas::dgemm;

fn main() {
    // 0.5⋅a⋅b + 2⋅c

    // allocate matrices
    let a = [ // (m, k) = (4, 5)
        1.0, 2.0,  0.0, 1.0, -1.0,
        2.0, 3.0, -1.0, 1.0,  1.0,
        1.0, 2.0,  0.0, 4.0, -1.0,
        4.0, 0.0,  3.0, 1.0,  1.0,
    ];
    let b = [ // (k, n) = (5, 3)
        1.0, 0.0, 0.0,
        0.0, 0.0, 3.0,
        0.0, 0.0, 1.0,
        1.0, 0.0, 1.0,
        0.0, 2.0, 0.0,
    ];
    let mut c = [ // (m, n) = (4, 3)
          0.50, 0.0,  0.25,
          0.25, 0.0, -0.25,
        -0.25, 0.0,  0.00,
        -0.25, 0.0,  0.00,
    ];

    // sizes
    let m = 4; // m = nrow(a) = a.M = nrow(c)
    let k = 5; // k = ncol(a) = a.N = nrow(b)
    let n = 3; // n = ncol(b) = b.N = ncol(c)

    // run dgemm
    let (trans_a, trans_b) = (false, false);
    let (alpha, beta) = (0.5, 2.0);
    dgemm(trans_a, trans_b, m, n, k, alpha, &a, &b, beta, &mut c);

    // check
    let correct = [
        2.0, -1.0, 4.0,
        2.0,  1.0, 4.0,
        2.0, -1.0, 5.0,
        2.0,  1.0, 2.0,
    ];
    assert_vec_approx_eq!(c, correct, 1e-15);
}

Solution of linear system

use russell_chk::assert_vec_approx_eq;
use russell_openblas::{dgesv, StrError};

fn main() -> Result<(), StrError> {
    // matrix
    let mut a = [
        2.0,  3.0,  0.0, 0.0, 0.0,
        3.0,  0.0,  4.0, 0.0, 6.0,
        0.0, -1.0, -3.0, 2.0, 0.0,
        0.0,  0.0,  1.0, 0.0, 0.0,
        0.0,  4.0,  2.0, 0.0, 1.0,
    ];

    // right-hand-side
    let mut b = vec![8.0, 45.0, -3.0, 3.0, 19.0];

    // solve b := x := A⁻¹ b
    let (n, nrhs) = (5_i32, 1_i32);
    let mut ipiv = vec![0; n as usize];
    dgesv(n, nrhs, &mut a, &mut ipiv, &mut b)?;

    // check
    let correct = &[1.0, 2.0, 3.0, 4.0, 5.0];
    assert_vec_approx_eq!(b, correct, 1e-14);
    Ok(())
}

Dependencies

~18MB
~194K SLoC