5
5
import importlib .metadata
6
6
7
7
from cuda import cuda
8
- from cuda .core .experimental ._utils import handle_return
8
+ from cuda .core .experimental ._utils import handle_return , precondition
9
9
10
10
_backend = {
11
11
"old" : {
@@ -106,30 +106,43 @@ class ObjectCode:
106
106
107
107
"""
108
108
109
- __slots__ = ("_handle" , "_code_type" , "_module" , "_loader" , "_sym_map" )
109
+ __slots__ = ("_handle" , "_backend_version" , "_jit_options" , " _code_type" , "_module" , "_loader" , "_sym_map" )
110
110
_supported_code_type = ("cubin" , "ptx" , "ltoir" , "fatbin" )
111
111
112
112
def __init__ (self , module , code_type , jit_options = None , * , symbol_mapping = None ):
113
113
if code_type not in self ._supported_code_type :
114
114
raise ValueError
115
115
_lazy_init ()
116
+
117
+ # handle is assigned during _lazy_load
116
118
self ._handle = None
119
+ self ._jit_options = jit_options
120
+
121
+ self ._backend_version = "new" if (_py_major_ver >= 12 and _driver_ver >= 12000 ) else "old"
122
+ self ._loader = _backend [self ._backend_version ]
123
+
124
+ self ._code_type = code_type
125
+ self ._module = module
126
+ self ._sym_map = {} if symbol_mapping is None else symbol_mapping
117
127
118
- backend = "new" if (_py_major_ver >= 12 and _driver_ver >= 12000 ) else "old"
119
- self ._loader = _backend [backend ]
128
+ # TODO: do we want to unload in a finalizer? Probably not..
120
129
130
+ def _lazy_load_module (self , * args , ** kwargs ):
131
+ if self ._handle is not None :
132
+ return
133
+ jit_options = self ._jit_options
134
+ module = self ._module
121
135
if isinstance (module , str ):
122
136
# TODO: this option is only taken by the new library APIs, but we have
123
137
# a bug that we can't easily support it just yet (NVIDIA/cuda-python#73).
124
138
if jit_options is not None :
125
139
raise ValueError
126
- module = module .encode ()
127
140
self ._handle = handle_return (self ._loader ["file" ](module ))
128
141
else :
129
142
assert isinstance (module , bytes )
130
143
if jit_options is None :
131
144
jit_options = {}
132
- if backend == "new" :
145
+ if self . _backend_version == "new" :
133
146
args = (
134
147
module ,
135
148
list (jit_options .keys ()),
@@ -141,15 +154,15 @@ def __init__(self, module, code_type, jit_options=None, *, symbol_mapping=None):
141
154
0 ,
142
155
)
143
156
else : # "old" backend
144
- args = (module , len (jit_options ), list (jit_options .keys ()), list (jit_options .values ()))
157
+ args = (
158
+ module ,
159
+ len (jit_options ),
160
+ list (jit_options .keys ()),
161
+ list (jit_options .values ()),
162
+ )
145
163
self ._handle = handle_return (self ._loader ["data" ](* args ))
146
164
147
- self ._code_type = code_type
148
- self ._module = module
149
- self ._sym_map = {} if symbol_mapping is None else symbol_mapping
150
-
151
- # TODO: do we want to unload in a finalizer? Probably not..
152
-
165
+ @precondition (_lazy_load_module )
153
166
def get_kernel (self , name ):
154
167
"""Return the :obj:`Kernel` of a specified name from this object code.
155
168
@@ -168,6 +181,7 @@ def get_kernel(self, name):
168
181
name = self ._sym_map [name ]
169
182
except KeyError :
170
183
name = name .encode ()
184
+
171
185
data = handle_return (self ._loader ["kernel" ](self ._handle , name ))
172
186
return Kernel ._from_obj (data , self )
173
187
0 commit comments