NVIDIA / NVIDIA/cuda-python

Inconsistent lifetime management across `from_handle` / `from_*` APIs

オープン
#1,989 コメント 10 件 リアクション 0 件 担当者 1 名 GitHub で見る

@Andy-Jost がすでに取り組んでいます。

2026年5月1日 から。

cuda.core enhancement P1
主要言語
Cython
スター
3.4k
フォーク
329
平均マージ
1日 21時間
マージ済み PR(30日)
113

説明

Summary

Audit of all public from_handle / from_* methods in cuda.core reveals several inconsistencies in how lifetime management is exposed to users. These should be resolved before the 1.0 stable release.

Inventory

Class Method Ownership Model
Stream from_handle(handle) Always non-owning (borrowed)
Kernel from_handle(handle, mod=) Non-owning ref; optional _keepalive holds ObjectCode
Buffer from_handle(ptr, size, mr=, owner=) 3 modes: non-owning / mr-deallocates / owner-ref
Event from_ipc_descriptor(...) Owns imported event
Buffer from_ipc_descriptor(...) Owns imported buffer
GraphicsResource from_gl_buffer(...) / from_gl_image(...) Owns GL registration
DeviceMemoryResource from_allocation_handle(...) / from_registry(uuid) Owns imported pool / retrieves existing
PinnedMemoryResource from_allocation_handle(...) / from_registry(uuid) Owns imported pool / retrieves existing
ObjectCode from_cubin/ptx/ltoir/fatbin/object/library() Owns module data
StridedMemoryView from_dlpack/cai/array_interface/buffer/any_interface() Always non-owning (view)

Inconsistencies

1. Stream.from_handle cannot opt into keeping an owner alive
  • Buffer.from_handle accepts owner= to hold a Python reference and prevent GC of the foreign allocator.
  • Kernel.from_handle accepts mod= to hold a reference and prevent GC of the parent ObjectCode/library.
  • Stream.from_handle has no equivalent parameter. It creates a borrowed stream with no way for the user to tie lifetime to an owner object.

The internal machinery already supports this — create_stream_handle_with_owner() in C++ accepts a Python owner and does Py_INCREF/DECREF. But from_handle() only passes the ephemeral _stream_holder wrapper as the owner, not the user's actual owner object.

Suggestion: Add an owner parameter to Stream.from_handle, consistent with Buffer.from_handle.

2. Event has no public from_handle()
  • Stream, Kernel, and Buffer all expose public from_handle() for wrapping foreign CUDA handles.
  • Event only has from_ipc_descriptor(). There is an internal _from_handle() (cdef), but no public way to wrap a foreign CUevent.

Suggestion: Add Event.from_handle(handle) for symmetry, with the same borrowed/non-owning semantics.

3. Kernel.from_handle docstring doesn't clearly document ownership
  • Stream.from_handle docstring explicitly says: "Stream lifetime is not managed, foreign object must remain alive while this stream is active."
  • Buffer.from_handle docstring explicitly documents all three ownership modes and when the pointer is/isn't freed.
  • Kernel.from_handle docstring mentions mod "provides library lifetime for foreign kernels" but doesn't clearly state that the kernel handle itself is non-owning and won't be destroyed on close/GC.

Suggestion: Improve the Kernel.from_handle docstring to match the clarity of the other two.

Additional observation

All from_handle() methods use @staticmethod, while from_ipc_descriptor() / from_gl_*() / from_allocation_handle() use @classmethod. This may be intentional (the latter group uses cls for subclassing support), but worth confirming as a deliberate convention and documenting if so.

-- Leo's bot

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。