Skip to content

Sparse arrays - #982

Draft
maleadt wants to merge 5 commits into
mainfrom
tb/sparse
Draft

maleadt wants to merge 5 commits into
mainfrom
tb/sparse

Conversation

@maleadt

@maleadt maleadt commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Metal.jl gets sparse vectors and matrices. GPUArrays 13 implements them for every back-end (JuliaGPU/GPUArrays.jl#745), and this PR names them for Metal storage and moves host sparse arrays to the GPU.

using Metal, SparseArrays, LinearAlgebra

A = mtl(sprand(1000, 1000, 0.01))  # MtlSparseMatrixCSR{Float32, Int32}
x = Metal.rand(Float32, 1000)

A * x            # sparse × dense
2 .* A .+ A      # broadcasting stays sparse
A * A'           # sparse × sparse
A[1:10, :]       # indexing
SparseMatrixCSC(A)  # back to the host
  • MtlSparseVector and MtlSparseMatrixCSR/CSC/COO are aliases of the GPUArrays types with MtlVector storage.
  • mtl(::SparseMatrixCSC) gives CSR, the best format for A * x. It uses Int32 indices when they fit, and narrows Float64 values like it does for dense arrays. adapt(MtlArray, A) keeps the format and types.
  • The constructors on the aliases convert host input on the host first, so Float64 data works. MtlArray(A) densifies on the device.
  • A new docs page covers the transfer policy and which format suits which operation.
  • Metal's broadcast specialization now only applies to GPU destinations, which avoids an ambiguity with in-place broadcasts into sparse arrays.

There is no vendor sparse library, so all products use GPUArrays' portable kernels. This is a minor release (1.13.0); Metal had no sparse support before. It supersedes #909.

Tested on an M1 and an M3 Pro (Julia 1.13): Metal's sparse tests (53) and GPUArrays' shared sparse testsuite on MtlArray (12,365), against GPUArrays tb/sparse. The package also loads on Julia 1.10.

The last commit (TEMP) points CI at the unregistered GPUArrays branch. Drop it before merging.

@maleadt maleadt added the arrays The array abstraction: broadcasting, mapreduce, indexing, views, generic linear algebra. label Oct 19, 2026
@maleadt
maleadt force-pushed the tb/sparse branch 5 times, most recently from c15be39 to 4e837cb Compare October 21, 2026 17:39
GPUArrays now implements the sparse formats generically, parametrized
on their storage, so Metal only names them for MtlVector storage
(MtlSparseVector, MtlSparseMatrixCSR/CSC/COO) and decides what mtl does
with host sparse arrays: matrices become CSR, indices Int32 when they
fit, and values follow the dense narrowing rules. Structural
adapt(MtlArray, S) keeps the format and types without Metal code.

This requires GPUArrays 13 (JuliaGPU/GPUArrays.jl#745).
Constructors on the aliases move their input to Metal, keeping its
format and types, and convert on the device; with explicit element
types, host inputs are converted on the host first so that Float64 data
can be used. MtlArray(A) densifies a sparse array on the device instead
of copying through the host. The usage page explains mtl's transfer
policy, the operations, and which format suits which operation.
materialize! and copyto! for MtlArrayStyle broadcasts accepted any
destination. With GPUArrays sparse arrays, which broadcast into Metal
storage but are not AbstractGPUArrays, that is ambiguous with GPUArrays'
in-place sparse broadcast and would run the dense kernel over the
sparse array's elements. Restrict both to GPU arrays and wrappers of
them; other destinations take the generic path.
Sparse array support needs GPUArrays 13, which is not a breaking change for Metal itself.
GPUArrays 13 is not registered yet. Drop this commit before merging.
@maleadt maleadt changed the title Sparse arrays on top of GPUArrays' generic formats Sparse arrays Nov 6, 2026
@codecov

codecov Bot commented Nov 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.95652% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.68%. Comparing base (806590b) to head (492d83b).

Files with missing lines Patch % Lines
src/sparse.jl 85.71% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #982      +/-   ##
==========================================
- Coverage   88.86%   83.68%   -5.18%     
==========================================
  Files         105      105              
  Lines        9399     8843     -556     
==========================================
- Hits         8352     7400     -952     
- Misses       1047     1443     +396     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arrays The array abstraction: broadcasting, mapreduce, indexing, views, generic linear algebra.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant