blas #
The V Basic Linear Algebra System
This package implements Basic Linear Algebra System (BLAS) routines in V.
| Backend | Description | Status | Compilation flag |
|---|---|---|---|
| BLAS | Pure V implementation; portable and dependency-free. | Stable | None |
| OpenBLAS | Optimized BLAS library. See OpenBLAS backend. | Stable | -d vsl_blas_cblas |
| System CBLAS | Host CBLAS for f32/f64 GEMM and GEMV, plus f64 DNRM2; performance depends on the provider. | Linux | -d vsl_blas_generic_cblas |
Pure V implementation
The pure V backend provides a zero-dependency, cross-platform implementation of BLAS Level 1, 2, and 3. It is the portable fallback; its dense matrix multiplication is not expected to match tuned OpenBLAS or other optimized C BLAS libraries. Use the CBLAS backend for performance-sensitive GEMM workloads.
For pure V GEMM, concurrency follows runtime.nr_jobs(); VJOBS caps the worker count on constrained systems. f64 GEMM distributes output tiles among workers. The row-major, no-transpose f32 SGEMM path uses V SIMD vectors and distributes larger row blocks among workers; small products stay serial to avoid worker startup overhead. Other f32 transpose layouts use the portable scalar path.
Run the benchmark from ~/.vmodules. Compile it first, then execute the binary in a separate memory-limited scope. -march=native is for measurements on this machine and creates a non-portable binary.
systemd-run --user --scope -p MemoryMax=4G -p MemorySwapMax=0 -- env VJOBS=2 \
v -no-parallel -cc gcc -prod -cflags "-march=native" -o /tmp/vsl-blas-bench \
./vsl/benchmarks/blas_bench.v
systemd-run --user --scope -p MemoryMax=1G -p MemorySwapMax=0 -- env VJOBS=2 \
/tmp/vsl-blas-bench
Available Functions
Level 1 BLAS:
ddot- Dot productsnrm2- Single-precision Euclidean normdnrm2- Euclidean normdasum- Sum of absolute valuesdaxpy- Vector addition (y = alpha*x + y)dscal- Vector scaling (x = alpha*x)dcopy- Vector copydswap- Vector swapidamax- Index of maximum absolute value
Level 2 BLAS:
sgemv- Single-precision general matrix-vector multiplydgemv- General matrix-vector multiplydger- Rank-1 updatedsymv- Symmetric matrix-vector multiplydsyr- Symmetric rank-1 updatedtrmv- Triangular matrix-vector multiplydtrsv- Triangular solve
Level 3 BLAS:
sgemm- Single-precision general matrix-matrix multiplydgemm- General matrix-matrix multiplydsymm- Symmetric matrix-matrix multiplydsyrk- Symmetric rank-k updatedsyr2k- Symmetric rank-2k updatedtrmm- Triangular matrix-matrix multiplydtrsm- Triangular solve with multiple RHS
The sgemv and dgemv routines accept row-major matrices and support .no_trans, .trans, .conj_trans, and .conj_no_trans. The generic system CBLAS build uses CBLAS GEMM and GEMV for positive vector increments; unsupported cases use the pure V implementation.
Therefore, its routines are a little more lower level than the ones in the package vsl.la.
OpenBLAS Backend
We provide a backend for the OpenBLAS library. This backend is probably the fastest one for all platforms but it requires the installation of the OpenBLAS library.
Use the compilation flag -d vsl_blas_cblas to use the OpenBLAS backend instead of the pure V implementation and make sure that the OpenBLAS library is installed in your system.
Check the section below for more information about installing the OpenBLAS library.
System CBLAS backend
The -d vsl_blas_generic_cblas flag links the host's libcblas; it does not select OpenBLAS or another tuned implementation. A system CBLAS can provide correctness and compatibility without improving performance. Benchmark the provider on the target machine, and use -d vsl_blas_cblas with OpenBLAS when you want VSL to link OpenBLAS explicitly.
Install dependencies
Homebrew (macOS)
brew install openblas
Debian/Ubuntu GNU Linux
libopenblas-dev is not needed when using the pure V backend.
sudo apt-get install -y --no-install-recommends \
gcc \
gfortran \
libopenblas-dev
Arch Linux/Manjaro GNU Linux
The best way of installing OpenBLAS is using blas-openblas.
sudo pacman -S blas-openblasfn cm_daxpy #
fn cm_daxpy(n int, alpha f64, x []f64, incx int, mut y []f64, incy int)
cm_daxpy exposes this operation as part of the public API.
fn cm_ddot #
fn cm_ddot(n int, x []f64, incx int, y []f64, incy int) f64
cm_ddot exposes this operation as part of the public API.
fn cm_dgemm #
fn cm_dgemm(trans_a Transpose, trans_b Transpose, m int, n int, k int, alpha f64, a []f64, lda int, b []f64, ldb int, beta f64, mut c []f64, ldc int)
cm_dgemm exposes this operation as part of the public API.
fn cm_dgemv #
fn cm_dgemv(trans Transpose, m int, n int, alpha f64, a []f64, lda int, x []f64, incx int, beta f64, mut y []f64, incy int)
cm_dgemv exposes this operation as part of the public API.
fn cm_dscal #
fn cm_dscal(n int, alpha f64, mut x []f64, incx int)
cm_dscal exposes this operation as part of the public API.
fn cm_dsyrk #
fn cm_dsyrk(uplo Uplo, trans Transpose, n int, k int, alpha f64, a []f64, lda int, beta f64, mut c []f64, ldc int)
cm_dsyrk exposes this operation as part of the public API.
fn cm_dtrsm #
fn cm_dtrsm(side Side, uplo Uplo, trans_a Transpose, diag Diagonal, m int, n int, alpha f64, a []f64, lda int, mut b []f64, ldb int)
cm_dtrsm exposes this operation as part of the public API.
fn col_major_complex_to_slice #
fn col_major_complex_to_slice(m int, n int, data []complex.Complex) [][]complex.Complex
col_major_complex_to_slice converts col-major matrix to nested slice
fn col_major_to_slice #
fn col_major_to_slice(m int, n int, data []f64) [][]f64
col_major_to_slice converts col-major matrix to nested slice
fn dasum #
fn dasum(n int, x []f64, incx int) f64
dasum exposes this operation as part of the public API.
fn daxpy #
fn daxpy(n int, alpha f64, x []f64, incx int, mut y []f64, incy int)
daxpy exposes this operation as part of the public API.
fn dcopy #
fn dcopy(n int, x []f64, incx int, mut y []f64, incy int)
dcopy exposes this operation as part of the public API.
fn ddot #
fn ddot(n int, x []f64, incx int, y []f64, incy int) f64
ddot exposes this operation as part of the public API.
fn dgbmv #
fn dgbmv(trans_a Transpose, m int, n int, kl int, ku int, alpha f64, a []f64, lda int, x []f64, incx int, beta f64, mut y []f64, incy int)
dgbmv exposes this operation as part of the public API.
fn dgemm #
fn dgemm(trans_a Transpose, trans_b Transpose, m int, n int, k int, alpha f64, a []f64, lda int, b []f64, ldb int, beta f64, mut cc []f64, ldc int)
dgemm exposes this operation as part of the public API.
fn dgemv #
fn dgemv(trans Transpose, m int, n int, alpha f64, a []f64, lda int, x []f64, incx int, beta f64, mut y []f64, incy int)
dgemv exposes this operation as part of the public API.
fn dger #
fn dger(m int, n int, alpha f64, x []f64, incx int, y []f64, incy int, mut a []f64, lda int)
dger exposes this operation as part of the public API.
fn dnrm2 #
fn dnrm2(n int, x []f64, incx int) f64
dnrm2 exposes this operation as part of the public API.
fn drot #
fn drot(n int, mut x []f64, incx int, mut y []f64, incy int, c f64, s f64)
drot exposes this operation as part of the public API.
fn dsbmv #
fn dsbmv(uplo Uplo, n int, k int, alpha f64, a []f64, lda int, x []f64, incx int, beta f64, mut y []f64, incy int)
dsbmv exposes this operation as part of the public API.
fn dscal #
fn dscal(n int, alpha f64, mut x []f64, incx int)
dscal exposes this operation as part of the public API.
fn dspmv #
fn dspmv(uplo Uplo, n int, alpha f64, ap []f64, x []f64, incx int, beta f64, mut y []f64, incy int)
dspmv exposes this operation as part of the public API.
fn dspr #
fn dspr(uplo Uplo, n int, alpha f64, x []f64, incx int, mut ap []f64)
dspr exposes this operation as part of the public API.
fn dspr2 #
fn dspr2(uplo Uplo, n int, alpha f64, x []f64, incx int, y []f64, incy int, mut ap []f64)
dspr2 exposes this operation as part of the public API.
fn dswap #
fn dswap(n int, mut x []f64, incx int, mut y []f64, incy int)
dswap exposes this operation as part of the public API.
fn dsymv #
fn dsymv(uplo Uplo, n int, alpha f64, a []f64, lda int, x []f64, incx int, beta f64, mut y []f64, incy int)
dsymv exposes this operation as part of the public API.
fn dsyr #
fn dsyr(uplo Uplo, n int, alpha f64, x []f64, incx int, mut a []f64, lda int)
dsyr exposes this operation as part of the public API.
fn dsyr2 #
fn dsyr2(uplo Uplo, n int, alpha f64, x []f64, incx int, y []f64, incy int, mut a []f64, lda int)
dsyr2 exposes this operation as part of the public API.
fn dsyr2k #
fn dsyr2k(uplo Uplo, trans_a Transpose, n int, k int, alpha f64, a []f64, lda int, b []f64, ldb int, beta f64, mut c []f64, ldc int)
dsyr2k exposes this operation as part of the public API.
fn dsyrk #
fn dsyrk(uplo Uplo, trans_a Transpose, n int, k int, alpha f64, a []f64, lda int, beta f64, mut c []f64, ldc int)
dsyrk exposes this operation as part of the public API.
fn dtbmv #
fn dtbmv(uplo Uplo, trans_a Transpose, diag Diagonal, n int, k int, a []f64, lda int, mut x []f64, incx int)
dtbmv exposes this operation as part of the public API.
fn dtbsv #
fn dtbsv(uplo Uplo, trans_a Transpose, diag Diagonal, n int, k int, a []f64, lda int, mut x []f64, incx int)
dtbsv exposes this operation as part of the public API.
fn dtpmv #
fn dtpmv(uplo Uplo, trans_a Transpose, diag Diagonal, n int, ap []f64, mut x []f64, incx int)
dtpmv exposes this operation as part of the public API.
fn dtpsv #
fn dtpsv(uplo Uplo, trans_a Transpose, diag Diagonal, n int, ap []f64, mut x []f64, incx int)
dtpsv exposes this operation as part of the public API.
fn dtrmm #
fn dtrmm(side Side, uplo Uplo, trans Transpose, diag Diagonal, m int, n int, alpha f64, a []f64, lda int, mut b []f64, ldb int)
dtrmm performs triangular matrix multiplication. Input matrices are expected in row-major format (as used by la/ module and tests). blas64.dtrmm uses row-major access pattern but validates ldb >= m (inconsistent). We pass matrices directly but ensure ldb >= m for validation.
fn dtrmv #
fn dtrmv(uplo Uplo, trans_a Transpose, diag Diagonal, n int, a []f64, lda int, mut x []f64, incx int)
dtrmv exposes this operation as part of the public API.
fn dtrsm #
fn dtrsm(side Side, uplo Uplo, trans Transpose, diag Diagonal, m int, n int, alpha f64, a []f64, lda int, mut b []f64, ldb int)
dtrsm exposes this operation as part of the public API.
fn dtrsv #
fn dtrsv(uplo Uplo, trans_a Transpose, diag Diagonal, n int, a []f64, lda int, mut x []f64, incx int)
dtrsv exposes this operation as part of the public API.
fn eigenvecs_build #
fn eigenvecs_build(mut vv []complex.Complex, wr []f64, wi []f64, v []f64)
eigenvecs_build builds complex eigenvectros created by Dgeev function
input: wr, wi: real and imag parts of eigenvalues. v: left or right eigenvectors from Dgeev.
output: vv: complex version of left or right eigenvector [pre-allocated].
NOTE: (no checks made).
n = wr.len = wi.len = v.len 2 * n = vv.len
fn eigenvecs_build_both #
fn eigenvecs_build_both(mut vvl []complex.Complex, mut vvr []complex.Complex, wr []f64, wi []f64, vl []f64, vr []f64)
eigenvecs_build_both builds complex left and right eigenvectros created by Dgeev function
input: wr, wi:real and imag parts of eigenvalues. vl, vr:left and right eigenvectors from Dgeev.
output: vvl, vvr:complex version of left and right eigenvectors [pre-allocated].
NOTE: (no checks made).
n = wr.len = wi.len = vl.len = vr.len 2 * n = vvl.len = vvr.len
fn extract_col #
fn extract_col(j int, m int, n int, a []f64) []f64
extract_col extracts j column from (m,n) col-major matrix
fn extract_col_complex #
fn extract_col_complex(j int, m int, n int, a []complex.Complex) []complex.Complex
extract_col_complex extracts j column from (m,n) col-major matrix (complex version)
fn extract_row #
fn extract_row(i int, m int, n int, a []f64) []f64
extract_row extracts i row from (m,n) col-major matrix
fn extract_row_complex #
fn extract_row_complex(i int, m int, n int, a []complex.Complex) []complex.Complex
extract_row_complex extracts i row from (m,n) col-major matrix (complex version)
fn from_blas64_diagonal #
fn from_blas64_diagonal(diag blas64.Diagonal) Diagonal
Convert blas64.Diagonal to VSL Diagonal
fn from_blas64_layout #
fn from_blas64_layout(layout blas64.MemoryLayout) MemoryLayout
Convert blas64.MemoryLayout to VSL MemoryLayout
fn from_blas64_side #
fn from_blas64_side(side blas64.Side) Side
Convert blas64.Side to VSL Side
fn from_blas64_transpose #
fn from_blas64_transpose(trans blas64.Transpose) Transpose
Convert blas64.Transpose to VSL Transpose
fn from_blas64_uplo #
fn from_blas64_uplo(uplo blas64.Uplo) Uplo
Convert blas64.Uplo to VSL Uplo
fn get_join_complex #
fn get_join_complex(v_real []f64, v_imag []f64) []complex.Complex
get_join_complex joins real and imag parts of array
fn get_split_complex #
fn get_split_complex(v []complex.Complex) ([]f64, []f64)
get_split_complex splits real and imag parts of array
fn idamax #
fn idamax(n int, x []f64, incx int) int
idamax exposes this operation as part of the public API.
fn join_complex #
fn join_complex(v_real []f64, v_imag []f64) []complex.Complex
join_complex joins real and imag parts of array
fn print_col_major #
fn print_col_major(m int, n int, data []f64, nfmt_ string) string
print_col_major prints matrix (without commas or brackets)
fn print_col_major_complex #
fn print_col_major_complex(m int, n int, data []complex.Complex, nfmt_r_ string, nfmt_i_ string) string
print_col_major_complex prints matrix (without commas or brackets). NOTE: if non-empty, nfmt_i must have '+' e.g. %+g
fn print_col_major_complex_v #
fn print_col_major_complex_v(m int, n int, data []complex.Complex, nfmt_r_ string, nfmt_i_ string) string
print_col_major_complex_v prints matrix in v format NOTE: if non-empty, nfmt_i must have '+' e.g. %+g
fn print_col_major_omplex_py #
fn print_col_major_omplex_py(m int, n int, data []complex.Complex, nfmt_r_ string, nfmt_i_ string) string
print_col_major_omplex_py prints matrix in Python format NOTE: if non-empty, nfmt_i must have '+' e.g. %+g
fn print_col_major_py #
fn print_col_major_py(m int, n int, data []f64, nfmt_ string) string
print_col_major_py prints matrix in Python format
fn print_col_major_v #
fn print_col_major_v(m int, n int, data []f64, nfmt_ string) string
print_col_major_v prints matrix in v format
fn set_num_threads #
fn set_num_threads(n int)
set_num_threads exposes this operation as part of the public API.
fn sgemm #
fn sgemm(trans_a Transpose, trans_b Transpose, m int, n int, k int, alpha f32, a []f32, lda int, b []f32, ldb int, beta f32, mut c []f32, ldc int)
sgemm computes a row-major single-precision matrix multiplication.
fn sgemv #
fn sgemv(trans Transpose, m int, n int, alpha f32, a []f32, lda int, x []f32, incx int, beta f32, mut y []f32, incy int)
sgemv computes y = alpha * op(A) * x + beta * y for row-major f32 matrices.
fn slice_to_col_major #
fn slice_to_col_major(a [][]f64) []f64
slice_to_col_major converts nested slice into an array representing a col-major matrix
NOTE: make sure to have at least 1x1 item
fn slice_to_col_major_complex #
fn slice_to_col_major_complex(a [][]complex.Complex) []complex.Complex
slice_to_col_major_complex converts nested slice into an array representing a col-major matrix of complex numbers.
data[i+j*m] = a[i][j]
NOTE: make sure to have at least 1x1 item
fn snrm2 #
fn snrm2(n int, x []f32, incx int) f32
snrm2 computes the Euclidean norm of a single-precision vector.
fn split_complex #
fn split_complex(v []complex.Complex) ([]f64, []f64)
split_complex splits real and imag parts of array
fn to_blas64_diagonal #
fn to_blas64_diagonal(diag Diagonal) blas64.Diagonal
Convert VSL Diagonal to blas64.Diagonal
fn to_blas64_layout #
fn to_blas64_layout(layout MemoryLayout) blas64.MemoryLayout
Convert VSL MemoryLayout to blas64.MemoryLayout
fn to_blas64_side #
fn to_blas64_side(side Side) blas64.Side
Convert VSL Side to blas64.Side
fn to_blas64_transpose #
fn to_blas64_transpose(trans Transpose) blas64.Transpose
Convert VSL Transpose to blas64.Transpose
fn to_blas64_uplo #
fn to_blas64_uplo(uplo Uplo) blas64.Uplo
Convert VSL Uplo to blas64.Uplo
enum Diagonal #
enum Diagonal {
non_unit = 131
unit = 132
}
Diagonal is used to specify whether the diagonal of a matrix is unit or non-unit.
enum MemoryLayout #
enum MemoryLayout {
row_major = 101
col_major = 102
}
MemoryLayout is used to specify the memory layout of a matrix.
enum Side #
enum Side {
left = 141
right = 142
}
Side is used to specify whether a matrix is on the left or right side in a matrix-matrix multiplication.
enum Transpose #
enum Transpose {
no_trans = 111
trans = 112
conj_trans = 113
conj_no_trans = 114
}
Transpose is used to specify the transposition of a matrix.
enum Uplo #
enum Uplo {
upper = 121
lower = 122
all = 99
}
Uplo is used to specify whether the upper or lower triangle of a matrix is
- README
- fn cm_daxpy
- fn cm_ddot
- fn cm_dgemm
- fn cm_dgemv
- fn cm_dscal
- fn cm_dsyrk
- fn cm_dtrsm
- fn col_major_complex_to_slice
- fn col_major_to_slice
- fn dasum
- fn daxpy
- fn dcopy
- fn ddot
- fn dgbmv
- fn dgemm
- fn dgemv
- fn dger
- fn dnrm2
- fn drot
- fn dsbmv
- fn dscal
- fn dspmv
- fn dspr
- fn dspr2
- fn dswap
- fn dsymv
- fn dsyr
- fn dsyr2
- fn dsyr2k
- fn dsyrk
- fn dtbmv
- fn dtbsv
- fn dtpmv
- fn dtpsv
- fn dtrmm
- fn dtrmv
- fn dtrsm
- fn dtrsv
- fn eigenvecs_build
- fn eigenvecs_build_both
- fn extract_col
- fn extract_col_complex
- fn extract_row
- fn extract_row_complex
- fn from_blas64_diagonal
- fn from_blas64_layout
- fn from_blas64_side
- fn from_blas64_transpose
- fn from_blas64_uplo
- fn get_join_complex
- fn get_split_complex
- fn idamax
- fn join_complex
- fn print_col_major
- fn print_col_major_complex
- fn print_col_major_complex_v
- fn print_col_major_omplex_py
- fn print_col_major_py
- fn print_col_major_v
- fn set_num_threads
- fn sgemm
- fn sgemv
- fn slice_to_col_major
- fn slice_to_col_major_complex
- fn snrm2
- fn split_complex
- fn to_blas64_diagonal
- fn to_blas64_layout
- fn to_blas64_side
- fn to_blas64_transpose
- fn to_blas64_uplo
- enum Diagonal
- enum MemoryLayout
- enum Side
- enum Transpose
- enum Uplo