Skip to content

GH-49437: [Python][GPU] Support legacy and native Numba CUDA context handles - #50923

Open
contentis wants to merge 1 commit into
apache:mainfrom
contentis:GH-49437-numba-context-handles
Open

contentis wants to merge 1 commit into
apache:mainfrom
contentis:GH-49437-numba-context-handles

Conversation

@contentis

@contentis contentis commented Aug 20, 2026 •

Copy link
Copy Markdown

Closes #49437

Numba-CUDA 0.28 changed CUDA context handles from ctypes.c_void_p to native cuda.bindings.driver.CUcontext objects. PyArrow currently expects incoming handles to have .value and also always returns ctypes.c_void_p when converting back to Numba.

I added a small compatibility layer which:

  • Accepts both legacy ctypes handles and native CUcontext objects.
  • Returns the representation expected by the installed Numba implementation.
  • Explicitly tests both representations instead of assuming .value.
  • Removes CUDA 11 from the Python CUDA jobs while keeping the existing C++ CUDA 11 coverage.
  • Numba and cuda.bindings are intentionally imported lazily here since they are optional dependencies. Not sure how happy I am with this bit but it was the best solution in my opinion.

There is also a temporary numpy<2.5 constraint for the Numba-CUDA environment. Numba-CUDA 0.30.4 currently uses the removed np.row_stack attribute with NumPy 2.5. This is already being handled upstream in NVIDIA/numba-cuda#916 and the constraint can be removed once that fix is released.

Testing

I tested the full CUDA Numba interop suite locally with:

  • Numba-CUDA 0.27: 50 passed
  • Numba-CUDA 0.28: 50 passed
  • Numba-CUDA 0.30.4: 50 passed

Cython compilation, linting and ShellCheck also pass.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #49437 has been automatically assigned in GitHub to PR creator.

@tadeja tadeja added the CI: Extra: CUDA Run extra CUDA CI label Aug 20, 2026

@raulcd raulcd 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.

Thanks so much for working on this @contentis !
While this has been tested locally with several versions of numba-cuda this is only tested on CI with numba-cuda latest, should we remove the comaptibility layer and make it only compatible with latest? Should we test with several numba-cuda versions on CI?
I am concerned that not having the "several compatibility" versions tested on CI will eventually fail and we will have some deprecated (untested) "compatibility" code.
@pitrou what do you think?

Comment thread python/pyarrow/_cuda.pyx
Comment on lines +35 to +37
if hasattr(handle, "value"):
return handle.value
return int(handle)

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.

Can you add comments telling which path is legacy or native?

Comment thread python/pyarrow/_cuda.pyx
from cuda.bindings.driver import CUcontext
return CUcontext(handle)

return ctypes.c_void_p(handle)

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.

This is the legacy path, right?

assert ctx.handle == ctx.to_numba().handle.value
converted = ctx.to_numba()
assert type(converted.handle) is type(nb_ctx.handle)
if isinstance(converted.handle, ctypes.c_void_p):

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.

Here as well, can you comment on which path corresponds to which Numba version(s)?

@pitrou

pitrou commented Sep 7, 2026

Copy link
Copy Markdown
Member

I am concerned that not having the "several compatibility" versions tested on CI will eventually fail and we will have some deprecated (untested) "compatibility" code.
@pitrou what do you think?

Given that this code is quite simple and exists in a module that is hardly every modified, I think it's ok.

It will obsolete in 1 or 2 years and we'll be able to remove it by then, I think.

@github-actions github-actions Bot added awaiting changes Awaiting changes and removed awaiting review Awaiting review labels Sep 7, 2026
@pitrou

pitrou commented Sep 7, 2026

Copy link
Copy Markdown
Member

@contentis Can you merge/rebase from main? There is an unexpected CI error here.

@rok

rok commented Oct 23, 2026

Copy link
Copy Markdown
Member

@contentis did you want to proceed with this PR?
If don't have this working we'll disable CUDA runners.

@tadeja
tadeja force-pushed the GH-49437-numba-context-handles branch from 7698132 to ae903b2 Compare October 30, 2026 08:50
@github-actions github-actions Bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Oct 30, 2026
@tadeja

tadeja commented Oct 30, 2026

Copy link
Copy Markdown
Member

I've rebased from main to help moving this along.

Also note that PR mentions:

There is also a temporary numpy<2.5 constraint for the Numba-CUDA environment. Numba-CUDA 0.30.4 currently uses the removed np.row_stack attribute with NumPy 2.5. This is already being handled upstream in NVIDIA/numba-cuda#916 and the constraint can be removed once that fix is released.

Unfortunately this is not getting fixed, got closed as not planned: NVIDIA/numba-cuda#907 (comment) :

Sorry for late response. numba-cuda is in maintenance mode now and we will unlikely fix this, I am afraid.
We encourage all users to transition to numba-cuda-mlir. v0.4.1+ should support any recent NumPy versions.

For existing numba-cuda users, use NumPy 2.4 or below.

@pitrou

pitrou commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Sorry for late response. numba-cuda is in maintenance mode now and we will unlikely fix this, I am afraid.

Here's a more radical suggestion: how about we deprecate Numba-CUDA support in PyArrow and then remove it? The code has almost not been touched since 2018 when it was first written by @pearu , and we don't seem to get any user feedback or reports about it (the only reason we are noticing problems is because of our own CI).

I don't think anyone cares at this point.

@pitrou

pitrou commented Oct 30, 2026

Copy link
Copy Markdown
Member

As for the Python CUDA CI jobs, we can simply skip test_cuda_numba_interop.py until we remove it.

@tadeja tadeja 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.

I'm only suggesting comments that could be added in slight chance that we don't take the probable path as per @pitrou

As for the Python CUDA CI jobs, we can simply skip test_cuda_numba_interop.py until we remove it.

fi

# Numba-CUDA 0.30.4 uses np.row_stack, which was removed in NumPy 2.5.
# TODO: Remove after https://github.com/NVIDIA/numba-cuda/pull/916 is released.

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.

Suggested change
# TODO: Remove after https://github.com/NVIDIA/numba-cuda/pull/916 is released.
# Upstream recommends NumPy <=2.4, no plan to fix this:
# https://github.com/NVIDIA/numba-cuda/issues/907#issuecomment-5620678407

Comment thread python/pyarrow/_cuda.pyx
Comment on lines +34 to +35
"""Return the integer value of a legacy or native Numba context handle."""
if hasattr(handle, "value"):

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.

Suggested change
"""Return the integer value of a legacy or native Numba context handle."""
if hasattr(handle, "value"):
"""Return the integer value of a legacy or native Numba context handle."""
# Legacy ctypes.c_void_p handle (built-in Numba CUDA or numba-cuda <0.28)
if hasattr(handle, "value"):

Comment thread python/pyarrow/_cuda.pyx
Comment on lines +36 to +37
return handle.value
return int(handle)

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.

Suggested change
return handle.value
return int(handle)
return handle.value
# Native cuda.bindings.driver.CUcontext handle (numba-cuda >=0.28)
return int(handle)

Comment thread python/pyarrow/_cuda.pyx
Comment on lines +51 to +53
return CUcontext(handle)

return ctypes.c_void_p(handle)

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.

Suggested change
return CUcontext(handle)
return ctypes.c_void_p(handle)
return CUcontext(handle)
# Legacy handle for built-in Numba CUDA and numba-cuda <0.28
return ctypes.c_void_p(handle)

Comment on lines +56 to +57
assert type(converted.handle) is type(nb_ctx.handle)
if isinstance(converted.handle, ctypes.c_void_p):

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.

Suggested change
assert type(converted.handle) is type(nb_ctx.handle)
if isinstance(converted.handle, ctypes.c_void_p):
assert type(converted.handle) is type(nb_ctx.handle)
# Built-in Numba CUDA and numba-cuda <0.28 use ctypes.c_void_p (legacy),
# numba-cuda >=0.28 uses cuda.bindings.driver.CUcontext
if isinstance(converted.handle, ctypes.c_void_p):

@pearu

pearu commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

Sorry for late response. numba-cuda is in maintenance mode now and we will unlikely fix this, I am afraid.

Here's a more radical suggestion: how about we deprecate Numba-CUDA support in PyArrow and then remove it? The code has almost not been touched since 2018 when it was first written by @pearu , and we don't seem to get any user feedback or reports about it (the only reason we are noticing problems is because of our own CI).

I don't think anyone cares at this point.

Or it just works :)

In any case, I agree that users should switch to the NVIDIA/numba-cuda-mlir approach (numba_cuda_mlir.cuda instead of numba.cuda) or use standard protocols such as DLPack or __cuda_array_interface__. For the export direction, CudaBuffer would need to implement these.

I looked for downstream users of from_numba/to_numba and found almost none. dora-rs was the only real user and dropped them in Aug 2026 (dora-rs/dora#3249). Other pyarrow.cuda users, like heavyai, rely only on the IPC and record-batch APIs. So deprecating and removing the numba methods seems fine, as long as the rest of pyarrow.cuda stays.

@raulcd

raulcd commented Oct 30, 2026

Copy link
Copy Markdown
Member

+1 on dropping support for numba-cuda

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Python][C++][GPU] Python Cuda jobs fail with 'cuda.bindings.driver.CUcontext' object has no attribute 'value'

6 participants