Table of Contents

Interface IBlasBackend

Namespace
NumSharp.Backends
Assembly
NumSharp.dll

An external BLAS/LAPACK a TensorEngine may delegate its matrix products and factorisations to.

public interface IBlasBackend

Remarks

NumSharp is 100 % managed C#: it has no native dependency and computes every matrix product with its own SIMD kernels. This interface is the ONE place an optional package can offer an alternative — it is a seam, not a requirement. With Blas left null (the default) nothing here is ever consulted.

Every member is Try-shaped on purpose: a backend answers only for the operand combinations it actually implements (an external CBLAS covers float32/ float64 and nothing else) and returns false for the rest, which the engine then computes with its own kernels. So installing a backend can change WHICH implementation runs, never WHETHER NumSharp can compute the product.

The reason to want one is not only speed. Two correct matrix products that sum in different orders give different bits, so a workload that must agree with another stack to the last bit — e.g. training a network twice and byte-comparing the weights — has to call that stack's own BLAS. See NumSharp.Interop.OpenBLAS and docs/stale-docs/GEMM_PARITY.md.

Reading the operands. An implementation needs raw pointers and strides, and NumSharp's public surface offers two spellings that are NOT interchangeable. Use (T*)a.GetData().Address + a.Shape.Offset together with a.Shape.Strides — that pair is consistent for every layout. Do NOT use a.GetData<T>().Address: for a non-contiguous view it returns a DENSIFIED COPY, so combining it with Shape.Strides reads outside the buffer and yields wrong numbers on exactly the sliced and transposed operands a matrix product is most often handed. Element strides, not bytes. Nothing here requires access to NumSharp's internals — a backend can live in any assembly.

The linear-algebra members below (the CBLAS product family and the LAPACK factorisations) are DEFAULT implementations returning false. That is what lets them be added without breaking the one backend that ships today (NumSharp.Interop.OpenBLAS's OpenBlasBackend, which answers only for dot/matmul at float32/float64) and any third-party implementation — a backend mentions only the members it serves, exactly as with TryMatMulBatched(NDArray, NDArray, NDArray).

Those two groups differ in one important way, and it is not their shape. The product family (inner/vdot/vecdot/matvec/vecmat) keeps the invariant the rest of this interface states: NumSharp computes them with its own managed kernels, so a backend changes WHICH implementation runs, never WHETHER the answer can be produced. The factorisation family CANNOT keep it — NumSharp.Core ships no managed LU, QR, SVD or eigensolver, so with no backend installed (or one that declines) the engine has nothing to fall back to and raises OpenBlasMissingBackendException. Callers of np.linalg must expect that; callers of the product family need not.

LAPACK operands. The operand-reading rule above applies unchanged, but LAPACK additionally wants column-major input, so an implementation will usually transpose or ask LAPACKE for row-major order; the engine hands over the operands untouched rather than guessing which a backend prefers.

Stacked operands. NumPy's linalg entry points are gufuncs over the trailing one or two axes, so every operand in the factorisation family may carry leading batch dimensions. A backend that only serves a single matrix returns false for a stacked one.

Properties

Info

A one-line description of the underlying library (path, symbols, thread count), for diagnostics. Never null.

string Info { get; }

Property Value

string

Methods

TryCholesky(NDArray, bool, out NDArray)

Computes np.linalg.cholesky (LAPACK potrf).

bool TryCholesky(NDArray a, bool upper, out NDArray result)

Parameters

a NDArray
upper bool

False for the lower-triangular factor (NumPy's default).

result NDArray

Returns

bool

False when this backend does not serve these operands.

TryDet(NDArray, out NDArray)

Computes np.linalg.det (LAPACK getrf).

bool TryDet(NDArray a, out NDArray result)

Parameters

a NDArray
result NDArray

Returns

bool

False when this backend does not serve these operands.

TryDot(NDArray, NDArray, out NDArray)

Computes np.dot(left, right), allocating the result.

bool TryDot(NDArray left, NDArray right, out NDArray result)

Parameters

left NDArray
right NDArray
result NDArray

The product, when this returns true; otherwise null.

Returns

bool

False when this backend does not serve these operands — the caller must then fall back to its own kernels, and result is meaningless.

Remarks

dot is a separate entry point from TryMatMul2D(NDArray, NDArray, NDArray) because the two are not the same operation for every shape: NumPy implements them with two different dispatchers, which disagree on some non-contiguous operands, and a backend claiming bit-parity has to reproduce that.

TryEig(NDArray, bool, out NDArray, out NDArray)

Computes np.linalg.eig / np.linalg.eigvals (LAPACK geev) for a general, not necessarily symmetric, matrix.

bool TryEig(NDArray a, bool computeVectors, out NDArray eigenvalues, out NDArray eigenvectors)

Parameters

a NDArray
computeVectors bool

False for eigvalseigenvectors is then null.

eigenvalues NDArray
eigenvectors NDArray

Returns

bool

False when this backend does not serve these operands.

TryEigh(NDArray, char, bool, out NDArray, out NDArray)

Computes np.linalg.eigh / np.linalg.eigvalsh (LAPACK syevd for a real symmetric operand, heevd for a complex Hermitian one).

bool TryEigh(NDArray a, char uplo, bool computeVectors, out NDArray eigenvalues, out NDArray eigenvectors)

Parameters

a NDArray
uplo char

'L' or 'U' — which triangle holds the data.

computeVectors bool

False for eigvalsh.

eigenvalues NDArray
eigenvectors NDArray

Returns

bool

False when this backend does not serve these operands.

TryInner(NDArray, NDArray, out NDArray)

Computes np.inner(a, b) — a sum product over the LAST axis of both operands.

bool TryInner(NDArray a, NDArray b, out NDArray result)

Parameters

a NDArray
b NDArray
result NDArray

Returns

bool

False when this backend does not serve these operands.

TryInv(NDArray, out NDArray)

Computes np.linalg.inv — NumPy solves a x = I with gesv rather than calling an explicit inversion routine.

bool TryInv(NDArray a, out NDArray result)

Parameters

a NDArray
result NDArray

Returns

bool

False when this backend does not serve these operands.

TryLstsq(NDArray, NDArray, double, out NDArray, out NDArray, out NDArray, out NDArray)

Computes np.linalg.lstsq (LAPACK gelsd) — the least-squares solution plus residuals, the effective rank and the singular values.

bool TryLstsq(NDArray a, NDArray b, double rcond, out NDArray solution, out NDArray residuals, out NDArray rank, out NDArray singularValues)

Parameters

a NDArray
b NDArray
rcond double

Singular-value cutoff, relative to the largest singular value.

solution NDArray
residuals NDArray
rank NDArray
singularValues NDArray

Returns

bool

False when this backend does not serve these operands.

TryMatMul2D(NDArray, NDArray, NDArray)

Computes the 2-D matrix product left @ right INTO result — the core of np.matmul, of @, and of every element of a stacked product.

bool TryMatMul2D(NDArray left, NDArray right, NDArray result)

Parameters

left NDArray
right NDArray
result NDArray

A pre-allocated (M, N) array of the promoted dtype. Written in full when this returns true; left untouched when it returns false.

Returns

bool

False when this backend does not serve these operands.

TryMatMulBatched(NDArray, NDArray, NDArray)

Computes a STACKED matrix product — the whole of np.matmul for operands of three dimensions or more — INTO result.

bool TryMatMulBatched(NDArray left, NDArray right, NDArray result)

Parameters

left NDArray

Already broadcast to (batch…, M, K).

right NDArray

Already broadcast to (batch…, K, N).

result NDArray

A pre-allocated (batch…, M, N) array of the promoted dtype.

Returns

bool

False when this backend does not serve these operands.

Remarks

Optional. The default returns false and the engine calls TryMatMul2D(NDArray, NDArray, NDArray) once per batch element instead, so a backend that does not care about stacked products need not mention this member at all — which is the point of it being a default implementation rather than a new required one.

Implement it when per-product setup can be amortised. The trailing two strides of each operand are the SAME for every element of a stack, so any route decision or scratch allocation derived from them is computed once — which is exactly why NumPy hoists that work out of its matmul gufunc's outer loop. Doing it per element instead costs more than the product itself once the matrices are small: measured on 2000 stacked 8×8 float32 products, per-element setup made an external OpenBLAS 20 % SLOWER than NumSharp's own managed GEMM.

TryMatvec(NDArray, NDArray, out NDArray)

Computes the np.matvec gufunc (m,n),(n)->(m), allocating the result — NumPy's gemv route.

bool TryMatvec(NDArray x1, NDArray x2, out NDArray result)

Parameters

x1 NDArray
x2 NDArray
result NDArray

Returns

bool

False when this backend does not serve these operands.

TryQr(NDArray, string, out NDArray, out NDArray)

Computes np.linalg.qr (LAPACK geqrf plus orgqr/ungqr).

bool TryQr(NDArray a, string mode, out NDArray q, out NDArray r)

Parameters

a NDArray
mode string

Already validated to one of "reduced", "complete", "r", "raw". For "r" only r is produced; for "raw" the pair is LAPACK's packed (h, tau) rather than (Q, R).

q NDArray
r NDArray

Returns

bool

False when this backend does not serve these operands.

TrySlogdet(NDArray, out NDArray, out NDArray)

Computes np.linalg.slogdet (LAPACK getrf) — the sign of the determinant and the natural log of its absolute value, which stays finite where det overflows.

bool TrySlogdet(NDArray a, out NDArray sign, out NDArray logabsdet)

Parameters

a NDArray
sign NDArray
logabsdet NDArray

Returns

bool

False when this backend does not serve these operands.

TrySolve(NDArray, NDArray, bool, out NDArray)

Computes np.linalg.solve (LAPACK gesv).

bool TrySolve(NDArray a, NDArray b, bool oneDimensionalRhs, out NDArray result)

Parameters

a NDArray
b NDArray
oneDimensionalRhs bool

True when b entered as a single vector — NumPy dispatches that to its solve1 gufunc (m,m),(m)->(m) rather than (m,m),(m,n)->(m,n).

result NDArray

Returns

bool

False when this backend does not serve these operands.

TrySvd(NDArray, bool, bool, out NDArray, out NDArray, out NDArray)

Computes np.linalg.svd / np.linalg.svdvals (LAPACK gesdd).

bool TrySvd(NDArray a, bool fullMatrices, bool computeUv, out NDArray u, out NDArray s, out NDArray vh)

Parameters

a NDArray
fullMatrices bool
computeUv bool

False for the singular values alone — u and vh are then null.

u NDArray
s NDArray
vh NDArray

Returns

bool

False when this backend does not serve these operands.

TryVdot(NDArray, NDArray, out NDArray)

Computes np.vdot(a, b) — both operands flattened to 1-D, a conjugated when complex, then a vector dot product. Always a 0-d result.

bool TryVdot(NDArray a, NDArray b, out NDArray result)

Parameters

a NDArray
b NDArray
result NDArray

Returns

bool

False when this backend does not serve these operands.

TryVecdot(NDArray, NDArray, out NDArray)

Computes the np.vecdot gufunc (n),(n)->(), allocating the result — x1 conjugated when complex.

bool TryVecdot(NDArray x1, NDArray x2, out NDArray result)

Parameters

x1 NDArray
x2 NDArray
result NDArray

Returns

bool

False when this backend does not serve these operands.

Remarks

Allocating rather than filling a caller-provided buffer (the shape TryMatMul2D(NDArray, NDArray, NDArray) takes) is deliberate for the three gufuncs: the loop shape is the broadcast of the operands' leading axes, and making the engine derive it up front would compute it twice on the path where the backend declines.

TryVecmat(NDArray, NDArray, out NDArray)

Computes the np.vecmat gufunc (n),(n,m)->(m), allocating the result — x1 conjugated when complex.

bool TryVecmat(NDArray x1, NDArray x2, out NDArray result)

Parameters

x1 NDArray
x2 NDArray
result NDArray

Returns

bool

False when this backend does not serve these operands.