22#
33# SPDX-License-Identifier: Apache-2.0
44
5- import sys
65import threading
76import weakref
87from collections import namedtuple
1918)
2019from cuda .core ._utils .cuda_utils import driver , get_binding_version , handle_return , precondition
2120
22-
2321# Lazy initialization state and synchronization
2422# For Python 3.13t (free-threaded builds), we use a lock to ensure thread-safe initialization.
2523# For regular Python builds with GIL, the lock overhead is minimal and the code remains safe.
3735 },
3836}
3937
38+
4039def _lazy_init ():
4140 """
4241 Initialize module-level state in a thread-safe manner.
43-
42+
4443 This function is thread-safe and suitable for both:
4544 - Regular Python builds (with GIL)
4645 - Python 3.13t free-threaded builds (without GIL)
47-
46+
4847 Uses double-checked locking pattern for performance:
4948 - Fast path: check without lock if already initialized
5049 - Slow path: acquire lock and initialize if needed
@@ -76,7 +75,7 @@ def _lazy_init():
7675 _driver_ver = handle_return (driver .cuDriverGetVersion ())
7776 if _py_major_ver >= 12 and _driver_ver >= 12040 :
7877 _backend ["new" ]["paraminfo" ] = driver .cuKernelGetParamInfo
79-
78+
8079 # Mark as initialized (must be last to ensure all state is set)
8180 _inited = True
8281
@@ -102,7 +101,7 @@ def _get_kernel_ctypes():
102101
103102def _get_backend_version ():
104103 """Get the backend version ("new" or "old") based on CUDA version.
105-
104+
106105 Returns "new" for CUDA 12.0+ (uses cuLibrary API), "old" otherwise (uses cuModule API).
107106 """
108107 return "new" if (_get_py_major_ver () >= 12 and _get_driver_ver () >= 12000 ) else "old"
@@ -493,7 +492,7 @@ def occupancy(self) -> KernelOccupancy:
493492 def from_handle (handle : int , mod : "ObjectCode" = None ) -> "Kernel" :
494493 """Creates a new :obj:`Kernel` object from a foreign kernel handle.
495494
496- Uses a CUfunction or CUkernel pointer address to create a new :obj:`Kernel` object.
495+ Uses a CUfunction or CUkernel pointer address to create a new :obj:`Kernel` object.
497496
498497 Parameters
499498 ----------
@@ -505,26 +504,26 @@ def from_handle(handle: int, mod: "ObjectCode" = None) -> "Kernel":
505504 a placeholder ObjectCode will be created. Note that without a proper
506505 ObjectCode, certain operations may be limited.
507506 """
508-
507+
509508 # Validate that handle is an integer
510509 if not isinstance (handle , int ):
511510 raise TypeError (f"handle must be an integer, got { type (handle ).__name__ } " )
512-
511+
513512 # Convert the integer handle to the appropriate driver type
514513 if _get_py_major_ver () >= 12 and _get_driver_ver () >= 12000 :
515514 # Try CUkernel first for newer CUDA versions
516515 kernel_obj = driver .CUkernel (handle )
517516 else :
518517 # Use CUfunction for older versions
519518 kernel_obj = driver .CUfunction (handle )
520-
519+
521520 # If no module provided, create a placeholder
522521 if mod is None :
523522 # Create a placeholder ObjectCode that won't try to load anything
524523 mod = ObjectCode ._init (b"" , "cubin" )
525524 # Set a dummy handle to prevent lazy loading
526525 mod ._handle = 1 # Non-null placeholder
527-
526+
528527 return Kernel ._from_obj (kernel_obj , mod )
529528
530529
@@ -694,7 +693,9 @@ def from_library(module: Union[bytes, str], *, name: str = "", symbol_mapping: d
694693 return ObjectCode ._init (module , "library" , name = name , symbol_mapping = symbol_mapping )
695694
696695 @staticmethod
697- def from_handle (handle : int , code_type : str = "cubin" , * , name : str = "" , symbol_mapping : dict | None = None ) -> "ObjectCode" :
696+ def from_handle (
697+ handle : int , code_type : str = "cubin" , * , name : str = "" , symbol_mapping : dict | None = None
698+ ) -> "ObjectCode" :
698699 """Create a new :obj:`ObjectCode` object from a foreign module handle.
699700
700701 Uses a CUmodule or CUlibrary pointer address to create a new :obj:`ObjectCode` object.
@@ -718,13 +719,13 @@ def from_handle(handle: int, code_type: str = "cubin", *, name: str = "", symbol
718719 # Create an ObjectCode instance with a placeholder module
719720 # The handle will be set directly, bypassing the lazy loading
720721 obj = ObjectCode ._init (b"" , code_type , name = name , symbol_mapping = symbol_mapping )
721-
722+
722723 # Set the handle directly from the foreign handle
723724 if obj ._backend_version == "new" :
724725 obj ._handle = driver .CUlibrary (handle )
725726 else :
726727 obj ._handle = driver .CUmodule (handle )
727-
728+
728729 return obj
729730
730731 # TODO: do we want to unload in a finalizer? Probably not..
0 commit comments