scverse / scverse/fast-array-utils

Why does fau need to know about numba internals for thread layer

Open
#215 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
15
Forks
5
Avg merge
10h 33m
Merged PRs (30d)
9

Description

I know that if numba exposed

numba.threading_layer_properties()  # {"name": "tbb", "threadsafe": True, "forksafe": True}

we wouldn't need this LAYER/priority mechanism's and usages across the repo. Which is very much prone to bugs and it has a bug. E.g., _threading_layer resolves a category by walking NUMBA_THREADING_LAYER_PRIORITY. numba doesn't do that: in _launch_threads it only consults the priority list in the default branch, and for safe/threadsafe/forksafe it builds its own fixed list, always tbb first https://github.com/numba/numba/blob/0.67.0/numba/np/ufunc/parallel.py#L473-L499 So with a non-default priority the two disagree:

 NUMBA_THREADING_LAYER_PRIORITY="omp workqueue tbb"

 THREADING_LAYER=threadsafe #  we predict omp        numba launches tbb
 THREADING_LAYER=forksafe     # we predict workqueue  numba launches tbb

For example in the forksafe case we predict workqueue, which isn't in LAYERS["threadsafe"], so _is_in_unsafe_thread_pool warns "unsupported threading environment" and drops to serial inside a thread pool, while the layer that actually launched (tbb) is thread-safe.

my proposals

from our side

We already launch a probe subprocess here:
https://github.com/scverse/fast-array-utils/blob/57365b8c424f5151ace666f8d7cdc585a94f0efb/src/fast_array_utils/numba/_parallel_runtime.py#L90-L104

why don't we just use this to get the information we need here?

from numba

If the subprocess probe is too hacky and we don't want to repeat it we ask numba to expose in an issue?

numba.threading_layer_properties()  # {"name": "tbb", "threadsafe": True, "forksafe": True}

how this would relate to https://github.com/scverse/fast-array-utils/issues/179

Once knowing the thread layer reliably we can also detect a fork and fall-back to serial in that case. If we also solve https://github.com/scverse/fast-array-utils/issues/213 then they would also get a speedup on top of this :)

def _is_in_unsafe_fork() -> bool:
    if not _forked: # see #179 for fork detection
        return False                              # not a child → nothing inherited
    layer = _launched_layer()
    return layer is not None and layer not in LAYERS["forksafe"]

Then having an always parallel/serial context manager settings would be its own new feature.

the solution which would remove all LAYER machinary

why not ask numba to fail gracefully? Like try: parallel() except UnsafeParallelError: serial(), would be a very reasonable ask, no? They can predict when their code would fail maybe? Or if it would need to be conservative maybe they would have a strict=True mode for it?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/fast_array_utils/numba/_parallel_runtime.py, especially the subprocess probe at lines 90-104, and compare its assumptions with Numba's _launch_threads logic in numba/np/ufunc/parallel.py lines 473-499. Review issues 179 and 213 for related constraints. The issue presents several possible directions but does not define one implementation or a concrete completion criterion.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
performance
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.