Skip to content

feat: compile njit functions with nogil=True - #217

Merged
flying-sheep merged 4 commits into
scverse:mainfrom
selmanozleyen:nogil-default
Sep 25, 2026
Merged

flying-sheep merged 4 commits into
scverse:mainfrom
selmanozleyen:nogil-default

Conversation

@selmanozleyen

@selmanozleyen selmanozleyen commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Part of #213.

Both the parallel and serial versions produced by fast_array_utils.numba.njit are now compiled with nogil=True, so the GIL is released while they run and callers can get real multithreaded speedups (e.g. dask's threaded scheduler, or squidpy's thread pools).

Behavior change: jitted functions that mutate shared buffers from multiple threads no longer get the GIL's accidental serialization. That was never a guarantee (see the race example in #213, which loses updates even with nogil=False), but it's worth a release note.

The other knobs discussed in #213 (error_model, inline, …) are left for follow-ups.

@flying-sheep I think the difference is due to different hardware. (my guess is nogil makes it more interruptible)

@codecov

codecov Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (eb9207a) to head (2eb277c).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #217   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           21        21           
  Lines          579       579           
=========================================
  Hits           579       579           

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

@codspeed

codspeed Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 232 untouched benchmarks
🆕 2 new benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
🆕 test_mean_var_threaded_benchmark[scipy.sparse.csc_array] N/A 446 ms N/A
🆕 test_mean_var_threaded_benchmark[scipy.sparse.csr_array] N/A 1.7 s N/A

Comparing selmanozleyen:nogil-default (2eb277c) with main (eb9207a)

Open in CodSpeed

@flying-sheep

Copy link
Copy Markdown
Member

wasn’t the idea to expose the knob? I see nogil=True and not nogil=nogil.

@selmanozleyen

Copy link
Copy Markdown
Member Author

wasn’t the idea to expose the knob? I see nogil=True and not nogil=nogil.

I saw it as a change with no regressions pretty much and I didn't want to change the __qualname__.

Also because here I wrote:

Besides the fallback of parallel and serial, I don't get why we wrap the whole njit tbh. For example why don't we provide nogil_thread_safety_fallback as a wrapper that only consumes parallel=True and gives the rest to njit as is?

So if we start passing all args one by one of njit, we kind of have a coupling that didn't seem very necessary. It could be just a kwargs we pass over. So I didn't want to go into that rabbithole and changed the default instead.

@flying-sheep

flying-sheep commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

As mentioned in person, no need to muck with the qualname since we don’t need to cache more versions. The only reason parallel is special is because we need to go for the non-parallel version in some situations

@selmanozleyen

selmanozleyen commented Sep 25, 2026 •

Copy link
Copy Markdown
Member Author

hi @flying-sheep , so after we chat then I still have to ask. Why do we not just pass the rest of the kwargs as just kwargs? Why does fau then need to know about kwargs other than parallelize? Is it for managing fau defaults? Then can't we just pass everything as is except the ones we want to control the defaults of? This way the whole #213 would be solved as well no? If somebody wanted inline they'd pass inline and it would be their and numba's problem

@flying-sheep

Copy link
Copy Markdown
Member

Typing. I’d rather update fau than have no autocomplete I think.

@selmanozleyen

Copy link
Copy Markdown
Member Author

ok then I think it's ready for review!

@flying-sheep flying-sheep added the run-gpu-ci Apply this label to run GPU CI once label Sep 25, 2026

@flying-sheep flying-sheep left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

great! one issue:

Comment thread src/fast_array_utils/numba/__init__.py Outdated
@flying-sheep

flying-sheep commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

there we go, I finally got all the variance taken care of on main.

@flying-sheep
flying-sheep merged commit 2941a7a into scverse:main Sep 25, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-gpu-ci Apply this label to run GPU CI once

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants