Skip to content

Add workspace to Factor for allocation-free CHOLMOD solves#727

Open
lorenzogambichler wants to merge 5 commits into
JuliaSparse:mainfrom
lorenzogambichler:cholmod-solve2-workspace
Open

Add workspace to Factor for allocation-free CHOLMOD solves#727
lorenzogambichler wants to merge 5 commits into
JuliaSparse:mainfrom
lorenzogambichler:cholmod-solve2-workspace

Conversation

@lorenzogambichler

@lorenzogambichler lorenzogambichler commented Jun 20, 2026

Copy link
Copy Markdown

Addresses #726

Makes repeated solves against a fixed sparse Cholesky factorization allocation-free by reusing CHOLMOD's cholmod_solve2 Y/E buffers across calls. Each Factor stores its own reusable workspace and a ReentrantLock, so the existing API stays the same and eliminates all julia-sided allocations.

F = cholesky(A)
for b in rhs
    ldiv!(x, F, b) # allocates ~16 bytes from CHOLMOD, as tested
end

@codecov

codecov Bot commented Jun 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.42%. Comparing base (7abbefa) to head (143e069).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #727      +/-   ##
==========================================
+ Coverage   84.40%   84.42%   +0.02%     
==========================================
  Files          13       13              
  Lines        9372     9381       +9     
==========================================
+ Hits         7910     7920      +10     
+ Misses       1462     1461       -1     

☔ 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.

@stevengj

stevengj commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

We already have a cholesky!(::CHOLMOD.Factor, ::SparseMatrixCSC) API, couldn't we just make that allocation-free by storing the workspace in the Factor?

@lorenzogambichler

Copy link
Copy Markdown
Author

I see, this is a good point. It seems like that is essentially how UmfpackLU handles the workspace caching? I'll rework the PR to add a workspace on the Factor with a default getworkspace accessor, essentially trying to mirror UmfpackLU.

…s cholmod_dense_struct wrappers and Y/E buffers so cholmod_solve2 reuses them across calls instead of reallocating
@lorenzogambichler lorenzogambichler force-pushed the cholmod-solve2-workspace branch from 5923f2f to d1b785c Compare July 7, 2026 19:00
@lorenzogambichler

Copy link
Copy Markdown
Author

Instead of an optional workspace argument, the workspace now lives inside the Factor. I tried to keep it similar to UmfpackWS and UmfpackLU in umfpack.jl. This keeps the 3-arg ldiv! API, while making it allocation-free.

@lorenzogambichler lorenzogambichler changed the title Add optional workspace for allocation-free CHOLMOD solves Add workspace to Factor for allocation-free CHOLMOD solves Jul 7, 2026
Comment thread src/solvers/cholmod.jl Outdated
Comment thread src/solvers/cholmod.jl Outdated
The workspace is finalizer-protected. The Y and E buffers are freed automatically
when the workspace is garbage-collected.
"""
mutable struct CholmodWorkspace

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure it's worth having a separate struct type here, as opposed to just making them fields of Factor

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main arguments for the separate struct are that it keeps the finalizer for the cholmod buffers separate from the free!s for the cholmod_factor pointer and it allows using a single :workspace enttry inside getproperty instead of five. The performance overhead should be negligible too. If you prefer the inline version, I can do that though.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the advantage of keeping the finalizer separate?

Can one ever use the workspace separately from a factor, or share the workspace between multiple factors?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's exactly one set of buffers per factor, right. I've added the fields directly to Factor.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants