Skip to content

Linear Algebra ​

cuNumeric.jl provides matrix multiplication, solves, Cholesky, eigen, SVD, QR, and related helpers for NDArray. For Einstein-index contractions, see Tensor Contractions.

Supported element types ​

All of the decompositions accept Float32, Float64, ComplexF32, and ComplexF64. Integer and Bool inputs are converted to Float64. As everywhere else in the package, that conversion needs @allowpromotion (or allowpromotion) only when it widens the element type, so Int64 and UInt64 pass through silently while Int32, smaller integers, and Bool do not.

In this section ​

PageTopics
Standard functionsMatrix and vector products, norms, linear systems, and helpers
FactorizationsCholesky, eigendecomposition, SVD, and QR
Batched operationsSolves and decompositions for stacks of matrices
Diagonal and identityStructured diagonal matrices and uniform scaling
TuningMulti-GPU selection rules, cutoffs, and block sizes

Which entry point to use ​

Single matrices use familiar LinearAlgebra functions. Most decompositions return standard factorization objects. QR returns cuNumeric's NDArrayQR. Stacks of matrices have no LinearAlgebra equivalent, so they get their own batched_* names.

Single matrix (2D)ReturnsStack of matrices (3D)
LinearAlgebra.cholesky(A)CholeskycuNumeric.batched_cholesky(A)
LinearAlgebra.eigen(A)EigencuNumeric.batched_eigen(A)
LinearAlgebra.eigvals(A)NDArraycuNumeric.batched_eigvals(A)
LinearAlgebra.svd(A)SVDnot supported
LinearAlgebra.qr(A)NDArrayQRnot supported
cuNumeric.solve(A, b), A \ bNDArraycuNumeric.batched_solve(A, B)

Not available yet ​

There is no public dense-matrix lu, matrix inv, or ldiv! yet (beyond the diagonal-matrix operations). Elementwise inv / ^-1 are unary operations, not matrix inverse.

Also missing: eigh / Hermitian eigen (needs Hermitian and Symmetric support on NDArray), and batched SVD and QR.

Reference ​

cuNumeric.NDArrayQR Type
julia
NDArrayQR <: LinearAlgebra.Factorization

QR factorization of an NDArray, holding the explicit factors Q and R with A ≈ Q * R.

The backend returns materialized factors rather than the packed Householder representation Base uses, so this is a distinct type from LinearAlgebra.QR and QRCompactWY. It destructures as (Q, R) and exposes F.Q and F.R.

source
Base.:\ Method
julia
A \ b

Solve A * x = b for a square 2D NDArray A. Equivalent to cuNumeric.solve.

source
LinearAlgebra.cholesky Method
julia
LinearAlgebra.cholesky(A::NDArray{T,2}) -> Cholesky

Cholesky factorization of the Hermitian positive-definite matrix A, returned as a LinearAlgebra.Cholesky object holding the lower factor L with A ≈ L * L'.

Only the lower triangle of A is read and, unlike Base, it is not checked for being Hermitian. A non-positive-definite input raises an ErrorException from the task rather than LinearAlgebra.PosDefException, so the check keyword is not supported.

Large matrices use cuSolverMp when available with multiple active GPUs. Other multi-processor configurations use cuPyNumeric's tiled Cholesky algorithm.

Accepted element types are Float32, Float64, ComplexF32, and ComplexF64. Integer and Bool inputs are converted to Float64. As everywhere else in the package, that conversion needs @allowpromotion only when it widens the element type, so Int64 and UInt64 pass through silently.

For a stack of matrices of shape (b, m, m) use cuNumeric.batched_cholesky.

source
LinearAlgebra.eigen Method
julia
LinearAlgebra.eigen(A::NDArray{T,2}) -> Eigen

Eigenvalues and right eigenvectors of the square matrix A, returned as a LinearAlgebra.Eigen object. Column j of F.vectors is the eigenvector for F.values[j].

Values and vectors are always complex, even when A is real with real eigenvalues. This follows the underlying LAPACK geev path and differs from Base, which returns real factors for such input.

Accepted element types are Float32, Float64, ComplexF32, and ComplexF64. Integer and Bool inputs are converted to Float64. As everywhere else in the package, that conversion needs @allowpromotion only when it widens the element type, so Int64 and UInt64 pass through silently.

For a stack of matrices of shape (b, m, m) use cuNumeric.batched_eigen.

source
LinearAlgebra.eigvals Method
julia
LinearAlgebra.eigvals(A::NDArray{T,2})

Eigenvalues of the square matrix A as a complex NDArray. See LinearAlgebra.eigen for the supported element types and for why the result is always complex.

source
LinearAlgebra.eigvecs Method
julia
LinearAlgebra.eigvecs(A::NDArray{T,2})

Right eigenvectors of the square matrix A, as columns of a complex NDArray. See LinearAlgebra.eigen for the supported element types.

source
LinearAlgebra.qr Method
julia
LinearAlgebra.qr(A::NDArray{T,2}) -> NDArrayQR

Reduced QR factorization of A, with A ≈ F.Q * F.R. For an m × n input and k = min(m, n), F.Q is m × k and F.R is k × n.

Large matrices automatically use cuSolverMp when available with multiple active GPUs, including tall and wide inputs.

See NDArrayQR for why this is not a LinearAlgebra.QRCompactWY.

Accepted element types are Float32, Float64, ComplexF32, and ComplexF64. Integer and Bool inputs are converted to Float64. As everywhere else in the package, that conversion needs @allowpromotion only when it widens the element type, so Int64 and UInt64 pass through silently.

source
LinearAlgebra.svd Method
julia
LinearAlgebra.svd(A::NDArray{T,2}; full=false) -> SVD

Singular value decomposition of A, returned as a LinearAlgebra.SVD object with A ≈ F.U * Diagonal(F.S) * F.Vt.

With m, n = size(A) and k = min(m, n), full=false gives an m × k F.U and a k × n F.Vt, and full=true gives m × m and n × n. F.S has length k and is real-valued for both real and complex input.

Destructuring an SVD yields (U, S, V) — the adjoint of F.Vt, not F.Vt itself. F.V is a lazy Adjoint wrapper, so operating on it falls back to scalar indexing until adjoint(::NDArray) is implemented; prefer F.Vt.

The backend only factors tall or square matrices (m >= n). A wide input throws ArgumentError rather than hitting the C++ m >= n assert.

Accepted element types are Float32, Float64, ComplexF32, and ComplexF64. Integer and Bool inputs are converted to Float64. As everywhere else in the package, that conversion needs @allowpromotion only when it widens the element type, so Int64 and UInt64 pass through silently.

source
cuNumeric.solve Method
julia
cuNumeric.solve(A, b)

Solve the linear system A * x = b.

A must be a square (m, m) matrix. b must have shape (m,) or (m, n). The result has the same shape as b.

Large systems automatically use cuSolverMp when it is available and Legate has multiple active GPUs. Algorithm selection follows cuPyNumeric 26.06.

Accepted element types are Float32, Float64, ComplexF32, and ComplexF64. Integer and Bool inputs are converted to Float64. As everywhere else in the package, that conversion needs @allowpromotion only when it widens the element type, so Int64 and UInt64 pass through silently.

For a stack of systems of shape (b, m, m) use cuNumeric.batched_solve.

See also \.

source
cuNumeric.batched_cholesky Method
julia
cuNumeric.batched_cholesky(A)

Cholesky factor of every matrix in the stack A, returned as a single array of the same shape. Each A[i, :, :] is factored independently into a lower triangular L with A[i, :, :] ≈ L * L'; the upper triangle is zeroed.

A must have shape (b, m, m). As in LinearAlgebra.cholesky, only the lower triangle is read and Hermitian-ness is not checked.

Accepted element types are Float32, Float64, ComplexF32, and ComplexF64. Integer and Bool inputs are converted to Float64. As everywhere else in the package, that conversion needs @allowpromotion only when it widens the element type, so Int64 and UInt64 pass through silently.

source
cuNumeric.batched_eigen Method
julia
cuNumeric.batched_eigen(A) -> (values, vectors)

Eigenvalues and right eigenvectors of every matrix in the stack A.

A must have shape (b, m, m). values has shape (b, m) and vectors has the shape of A, with vectors[i, :, j] the eigenvector for values[i, j].

Both results are always complex, even for real input. See LinearAlgebra.eigen.

source
cuNumeric.batched_eigvals Method
julia
cuNumeric.batched_eigvals(A)

Eigenvalues of every matrix in the stack A, as a complex array of shape (b, m). See cuNumeric.batched_eigen.

source
cuNumeric.batched_solve Method
julia
cuNumeric.batched_solve(A, B)

Solve a stack of linear systems A * X = B.

A must have shape (b, m, m) and B shape (b, m, n). The result has the same shape as B.

Accepted element types are Float32, Float64, ComplexF32, and ComplexF64. Integer and Bool inputs are converted to Float64. As everywhere else in the package, that conversion needs @allowpromotion only when it widens the element type, so Int64 and UInt64 pass through silently.

For a single system use cuNumeric.solve.

source
LinearAlgebra.axpby! Method
julia
axpby!(α, x::NDArray, β, y::NDArray)

Update and return y with y = α * x + β * y.

source
LinearAlgebra.axpy! Method
julia
axpy!(α, x::NDArray, y::NDArray)

Update and return y with y = α * x + y.

source
LinearAlgebra.dot Method
julia
dot(x::NDArray, y::NDArray)

Return the vector inner product as a CNScalar. Complex inputs conjugate x.

source
LinearAlgebra.mul! Method
julia
mul!(y::NDArray, A::NDArray, x::NDArray, α, β)

Store α * A * x + β * y in y. The destination must not alias an input. α and β accept host numbers, 0D NDArray{T,0} values, or CNScalar wrappers.

source
LinearAlgebra.mul! Method
julia
mul!(y::NDArray, A::NDArray, x::NDArray)

Store the matrix-vector product A * x in y.

source
LinearAlgebra.mul! Method
julia
mul!(C::NDArray, A::NDArray, B::NDArray, α, β)

Store α * A * B + β * C in C. The destination must not alias an input. α and β accept host numbers, 0D NDArray{T,0} values, or CNScalar wrappers.

source
LinearAlgebra.norm Method
julia
norm(x::NDArray, p::Real=2)

Return the entrywise p-norm as a real CNScalar, not a matrix operator norm. Dense-array norms currently require a GPU. Unscaled accumulation can overflow or underflow.

source
cuNumeric.diag Method
julia
cuNumeric.diag(arr::NDArray; k=0)

Extract the k-th diagonal from a 2D NDArray.

source
cuNumeric.diagonal Method
julia
cuNumeric.diagonal(arr::NDArray; offset=0, dims=(1, 2))

Extract the diagonal of arr along two 1-based axes dims. The result has rank ndims(arr) - 1, with the diagonal stored as the last axis. offset selects a superdiagonal (> 0) or subdiagonal (< 0), matching LinearAlgebra.diag.

For a 2D matrix this is the same 1D diagonal as diag. For N > 2 the non-diagonal axes are kept in order, followed by the extracted diagonal.

source
cuNumeric.trace Method
julia
cuNumeric.trace(arr::NDArray; offset=0, a1=0, a2=1)

Compute the trace (sum of a diagonal) of the NDArray. Returns a 0-dimensional NDArray. The accumulator type follows promotions of other reductions like sum.

source