Store and multiply matrices in factored form M = U*V without forming the full dense matrix.
When U is m×k and V is k×n, a product A*B costs O(mk²n) instead of O(m²kn) — a
significant saving when k is small relative to m and n.
using Pkg
Pkg.add("FactoredMatrices")using FactoredMatrices
U = randn(100, 5) # 100×5
V = randn(5, 80) # 5×80
A = FactoredMatrix(U, V) # represents the 100×80 matrix U*V
x = randn(80)
y = A * x # 100-element result, no 100×80 matrix formed
B = randn(80, 3)
C = A * B # 100×3 resultFactoredMatrix supports adjoints, transposes, mul!, dot, and conversion to a
dense Matrix.
For tight loops where allocations matter, pre-allocate a Workspace and pass it
via the cache keyword:
using LinearAlgebra
ws = FactoredMatrices.Workspace(A, size(B, 2)) # scratch buffers sized for A*B products
C = similar(A * B) # pre-allocate output
for _ in 1:1000
mul!(C, A, B; cache=ws) # no allocation
endThe same Workspace can be reused across calls (including adjoint/transpose products)
as long as the operand sizes do not change. Create one Workspace per thread when
multiplying concurrently against the same A.
One can achieve some of this functionality using other, more general packages. In particular, see: