Skip to content

ComputeGraph concurrency#5556

Draft
ffreyer wants to merge 20 commits into
ff/breaking-0.25from
ff/compute-graph-concurrency
Draft

ComputeGraph concurrency#5556
ffreyer wants to merge 20 commits into
ff/breaking-0.25from
ff/compute-graph-concurrency

Conversation

@ffreyer
Copy link
Copy Markdown
Collaborator

@ffreyer ffreyer commented Mar 15, 2026

Description

This is another attempt at getting ComputeGraph updates and resolution working concurrently, without just placing everything behind a global lock.

This version includes locks for every edges which get locked behind a global lock before resolve!() does work. The edge locks then release once the edges outputs are no longer in use by any child edge. mark_dirty!() locks the global lock as resolve!() preparation requires state to be frozen. mark_dirty!(computed) also locks the parent edge of the compute note it marks because it sets state used in edge resolution. Updates lock their parent edge for the same reason. update!() specifically lock the parent edge of all the inputs being set together, so the update remains synchronized.

Notes:

  • Updating a node from within a computegraph callback may corrupt state (if the lock passes) or cause a deadlock (if it doesn't) or do nothing bad (if the edge is not an active part of this resolution anymore. This means it's not a direct parent of the edge causing the update and there is no other way to reach it from any (recursive) child of the edge causing the update.)

Performance:
This is 10-20% slower than #5546 for me when rendering a simple plot in an Axis with the camera moving the Axis each frame.

f, a, p = scatter(rand(Point2f, 100))
screen = display(f)
e = events(f)
begin # compile interaction
    e.mouseposition[] = (200.0, 200.0) .+ 50.0 .* (cos(0), sin(0))
    e.mousebutton[] = Makie.MouseButtonEvent(Mouse.right, Mouse.press)
    e.mouseposition[] = (200.0, 200.0) .+ 50.0 .* (cos(0.5), sin(0.5))
    yield()
    e.mousebutton[] = Makie.MouseButtonEvent(Mouse.right, Mouse.release)
end

@time timings = let
    e = events(f)
    e.mouseposition[] = (200.0, 200.0) .+ 50.0 .* (cos(0), sin(0))
    e.mousebutton[] = Makie.MouseButtonEvent(Mouse.right, Mouse.press)
    idx = 1
    timings = GLMakie.render_asap(screen, 10_000) do
        e.mouseposition[] = (200.0, 200.0) .+ 50.0 .* (cos(0.03 * idx), sin(0.03 * idx))
        idx += 1
    end
    e.mousebutton[] = Makie.MouseButtonEvent(Mouse.right, Mouse.release)
    timings
end

# ms frametimes
mean(timings) * 1000
median(timings) * 1000
mean(sort(timings)[1:900]) * 1000

TODO:

  • Consider swapping out the global lock for a lock shared between all connected graphs. (I.e. if graph A feeds into graph B, they both must have the same lock to correctly protect resolve setup)
  • Consider some sort of asymmetric (global/multi-graph) lock for update/mark_dirty vs resolve which allows nothing else to run while resolve is setting up, but does allow multiple mark_dirty's to run at the same time. Multiple overlapping mark_dirty's will, at worst, do duplicate work, marking the same edge.dirty[] = true multiple times. Updates still have edge locks to protect against overwrite.
  • guard against nested resolve triggered by Observable (i.e. don't allow an update from resolve to trigger another resolve through onchange. This should allow inputs to be updated in a loop even if they trigger an Observable)

Type of change

Delete options that do not apply:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist

  • Added an entry in CHANGELOG.md (for new features and breaking changes)
  • Added or changed relevant sections in the documentation
  • Added unit tests for new algorithms, conversion methods, etc.
  • Added reference image tests for new plotting functions, recipes, visual options, etc.

@github-project-automation github-project-automation Bot moved this to Work in progress in PR review Mar 15, 2026
@MakieBot
Copy link
Copy Markdown
Collaborator

MakieBot commented Mar 15, 2026

Benchmark Results

SHA: 00d86f538712d0e3103667348f51136234abfc89

Warning

These results are subject to substantial noise because GitHub's CI runs on shared machines that are not ideally suited for benchmarking.

GLMakie
CairoMakie
WGLMakie

Base automatically changed from ff/compute-blocks to ff/breaking-0.25 March 17, 2026 13:06
@ffreyer ffreyer mentioned this pull request Mar 18, 2026
24 tasks
@ffreyer ffreyer force-pushed the ff/compute-graph-concurrency branch from 91144d0 to 8eaa92a Compare March 19, 2026 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Work in progress

Development

Successfully merging this pull request may close these issues.

2 participants