xref: /aosp_15_r20/external/pytorch/torch/csrc/Device.cpp (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/Device.h>
2*da0073e9SAndroid Build Coastguard Worker 
3*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/Exceptions.h>
4*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/object_ptr.h>
5*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/pybind.h>
6*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/python_arg_parser.h>
7*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/python_numbers.h>
8*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/python_strings.h>
9*da0073e9SAndroid Build Coastguard Worker 
10*da0073e9SAndroid Build Coastguard Worker #include <ATen/Device.h>
11*da0073e9SAndroid Build Coastguard Worker #include <c10/util/Exception.h>
12*da0073e9SAndroid Build Coastguard Worker 
13*da0073e9SAndroid Build Coastguard Worker #include <structmember.h>
14*da0073e9SAndroid Build Coastguard Worker #include <limits>
15*da0073e9SAndroid Build Coastguard Worker #include <sstream>
16*da0073e9SAndroid Build Coastguard Worker 
17*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
18*da0073e9SAndroid Build Coastguard Worker PyObject* THPUpperModuleOfDevice = nullptr;
19*da0073e9SAndroid Build Coastguard Worker 
THPDevice_New(const at::Device & device)20*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_New(const at::Device& device) {
21*da0073e9SAndroid Build Coastguard Worker   auto type = (PyTypeObject*)&THPDeviceType;
22*da0073e9SAndroid Build Coastguard Worker   auto self = THPObjectPtr{type->tp_alloc(type, 0)};
23*da0073e9SAndroid Build Coastguard Worker   if (!self)
24*da0073e9SAndroid Build Coastguard Worker     throw python_error();
25*da0073e9SAndroid Build Coastguard Worker   auto self_ = reinterpret_cast<THPDevice*>(self.get());
26*da0073e9SAndroid Build Coastguard Worker   self_->device = device;
27*da0073e9SAndroid Build Coastguard Worker   return self.release();
28*da0073e9SAndroid Build Coastguard Worker }
29*da0073e9SAndroid Build Coastguard Worker 
THPDevice_repr(THPDevice * self)30*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_repr(THPDevice* self) {
31*da0073e9SAndroid Build Coastguard Worker   std::ostringstream oss;
32*da0073e9SAndroid Build Coastguard Worker   oss << "device(type=\'" << self->device.type() << "\'";
33*da0073e9SAndroid Build Coastguard Worker   if (self->device.has_index()) {
34*da0073e9SAndroid Build Coastguard Worker     // `self->device.index()` returns uint8_t which is treated as ascii while
35*da0073e9SAndroid Build Coastguard Worker     // printing, hence casting it to uint16_t.
36*da0073e9SAndroid Build Coastguard Worker     // https://stackoverflow.com/questions/19562103/uint8-t-cant-be-printed-with-cout
37*da0073e9SAndroid Build Coastguard Worker     oss << ", index=" << static_cast<uint16_t>(self->device.index());
38*da0073e9SAndroid Build Coastguard Worker   }
39*da0073e9SAndroid Build Coastguard Worker   oss << ")";
40*da0073e9SAndroid Build Coastguard Worker   return THPUtils_packString(oss.str().c_str());
41*da0073e9SAndroid Build Coastguard Worker }
42*da0073e9SAndroid Build Coastguard Worker 
THPDevice_str(THPDevice * self)43*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_str(THPDevice* self) {
44*da0073e9SAndroid Build Coastguard Worker   std::ostringstream oss;
45*da0073e9SAndroid Build Coastguard Worker   oss << self->device;
46*da0073e9SAndroid Build Coastguard Worker   return THPUtils_packString(oss.str().c_str());
47*da0073e9SAndroid Build Coastguard Worker }
48*da0073e9SAndroid Build Coastguard Worker 
THPDevice_pynew(PyTypeObject * type,PyObject * args,PyObject * kwargs)49*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_pynew(
50*da0073e9SAndroid Build Coastguard Worker     PyTypeObject* type,
51*da0073e9SAndroid Build Coastguard Worker     PyObject* args,
52*da0073e9SAndroid Build Coastguard Worker     PyObject* kwargs) {
53*da0073e9SAndroid Build Coastguard Worker   HANDLE_TH_ERRORS
54*da0073e9SAndroid Build Coastguard Worker   static torch::PythonArgParser parser(
55*da0073e9SAndroid Build Coastguard Worker       {"device(Device device)",
56*da0073e9SAndroid Build Coastguard Worker        "device(c10::string_view type, int64_t? index=-1)"});
57*da0073e9SAndroid Build Coastguard Worker   torch::ParsedArgs<2> parsed_args;
58*da0073e9SAndroid Build Coastguard Worker   auto r = parser.parse(args, kwargs, parsed_args);
59*da0073e9SAndroid Build Coastguard Worker   if (r.has_torch_function()) {
60*da0073e9SAndroid Build Coastguard Worker     return handle_torch_function(
61*da0073e9SAndroid Build Coastguard Worker         r, nullptr, args, kwargs, THPUpperModuleOfDevice, "torch");
62*da0073e9SAndroid Build Coastguard Worker   }
63*da0073e9SAndroid Build Coastguard Worker   if (r.idx == 0) {
64*da0073e9SAndroid Build Coastguard Worker     auto device = r.device(0);
65*da0073e9SAndroid Build Coastguard Worker     return THPDevice_New(device);
66*da0073e9SAndroid Build Coastguard Worker   } else if (r.idx == 1) {
67*da0073e9SAndroid Build Coastguard Worker     auto as_device = r.device(0); // this works, because device can take strings
68*da0073e9SAndroid Build Coastguard Worker     if (as_device.has_index()) {
69*da0073e9SAndroid Build Coastguard Worker       auto device_type = r.string(0);
70*da0073e9SAndroid Build Coastguard Worker       throw std::runtime_error(
71*da0073e9SAndroid Build Coastguard Worker           "type (string) must not include an index because index "
72*da0073e9SAndroid Build Coastguard Worker           "was passed explicitly: " +
73*da0073e9SAndroid Build Coastguard Worker           device_type);
74*da0073e9SAndroid Build Coastguard Worker     }
75*da0073e9SAndroid Build Coastguard Worker     int64_t device_index = -1;
76*da0073e9SAndroid Build Coastguard Worker     if (!r.isNone(1)) {
77*da0073e9SAndroid Build Coastguard Worker       device_index = r.toInt64(1);
78*da0073e9SAndroid Build Coastguard Worker       // -1 is allowed in ATen/C++, to mean the default device, but not in
79*da0073e9SAndroid Build Coastguard Worker       // Python.
80*da0073e9SAndroid Build Coastguard Worker       TORCH_CHECK(device_index >= 0, "Device index must not be negative");
81*da0073e9SAndroid Build Coastguard Worker     }
82*da0073e9SAndroid Build Coastguard Worker     at::Device device(
83*da0073e9SAndroid Build Coastguard Worker         as_device.type(), static_cast<c10::DeviceIndex>(device_index));
84*da0073e9SAndroid Build Coastguard Worker     return THPDevice_New(device);
85*da0073e9SAndroid Build Coastguard Worker   }
86*da0073e9SAndroid Build Coastguard Worker   Py_RETURN_NONE;
87*da0073e9SAndroid Build Coastguard Worker   END_HANDLE_TH_ERRORS
88*da0073e9SAndroid Build Coastguard Worker }
89*da0073e9SAndroid Build Coastguard Worker 
THPDevice_type(THPDevice * self,PyObject * noargs)90*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_type(THPDevice* self, PyObject* noargs) {
91*da0073e9SAndroid Build Coastguard Worker   HANDLE_TH_ERRORS
92*da0073e9SAndroid Build Coastguard Worker   std::ostringstream oss;
93*da0073e9SAndroid Build Coastguard Worker   oss << self->device.type();
94*da0073e9SAndroid Build Coastguard Worker   return THPUtils_packString(oss.str().c_str());
95*da0073e9SAndroid Build Coastguard Worker   Py_RETURN_NONE;
96*da0073e9SAndroid Build Coastguard Worker   END_HANDLE_TH_ERRORS
97*da0073e9SAndroid Build Coastguard Worker }
98*da0073e9SAndroid Build Coastguard Worker 
THPDevice_index(THPDevice * self,PyObject * noargs)99*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_index(THPDevice* self, PyObject* noargs) {
100*da0073e9SAndroid Build Coastguard Worker   HANDLE_TH_ERRORS
101*da0073e9SAndroid Build Coastguard Worker   if (self->device.has_index()) {
102*da0073e9SAndroid Build Coastguard Worker     return THPUtils_packInt64(self->device.index());
103*da0073e9SAndroid Build Coastguard Worker   } else {
104*da0073e9SAndroid Build Coastguard Worker     Py_RETURN_NONE;
105*da0073e9SAndroid Build Coastguard Worker   }
106*da0073e9SAndroid Build Coastguard Worker   END_HANDLE_TH_ERRORS
107*da0073e9SAndroid Build Coastguard Worker }
108*da0073e9SAndroid Build Coastguard Worker 
THPDevice_hash(THPDevice * self)109*da0073e9SAndroid Build Coastguard Worker static Py_ssize_t THPDevice_hash(THPDevice* self) {
110*da0073e9SAndroid Build Coastguard Worker   HANDLE_TH_ERRORS
111*da0073e9SAndroid Build Coastguard Worker   return static_cast<Py_ssize_t>(
112*da0073e9SAndroid Build Coastguard Worker       std::hash<at::Device>{}(self->device) %
113*da0073e9SAndroid Build Coastguard Worker       std::numeric_limits<Py_ssize_t>::max());
114*da0073e9SAndroid Build Coastguard Worker   END_HANDLE_TH_ERRORS_RET(-1)
115*da0073e9SAndroid Build Coastguard Worker }
116*da0073e9SAndroid Build Coastguard Worker 
THPDevice_rc(PyObject * a,PyObject * b,int op)117*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_rc(PyObject* a, PyObject* b, int op) {
118*da0073e9SAndroid Build Coastguard Worker   HANDLE_TH_ERRORS
119*da0073e9SAndroid Build Coastguard Worker   if (!THPDevice_Check(a) || !THPDevice_Check(b)) {
120*da0073e9SAndroid Build Coastguard Worker     // Py_RETURN_NOTIMPLEMENTED not in python 2.
121*da0073e9SAndroid Build Coastguard Worker     Py_INCREF(Py_NotImplemented);
122*da0073e9SAndroid Build Coastguard Worker     return Py_NotImplemented;
123*da0073e9SAndroid Build Coastguard Worker   }
124*da0073e9SAndroid Build Coastguard Worker   THPDevice* da = reinterpret_cast<THPDevice*>(a);
125*da0073e9SAndroid Build Coastguard Worker   THPDevice* db = reinterpret_cast<THPDevice*>(b);
126*da0073e9SAndroid Build Coastguard Worker 
127*da0073e9SAndroid Build Coastguard Worker   switch (op) {
128*da0073e9SAndroid Build Coastguard Worker     case Py_EQ:
129*da0073e9SAndroid Build Coastguard Worker       if (da->device == db->device) {
130*da0073e9SAndroid Build Coastguard Worker         Py_RETURN_TRUE;
131*da0073e9SAndroid Build Coastguard Worker       } else {
132*da0073e9SAndroid Build Coastguard Worker         Py_RETURN_FALSE;
133*da0073e9SAndroid Build Coastguard Worker       }
134*da0073e9SAndroid Build Coastguard Worker     case Py_NE:
135*da0073e9SAndroid Build Coastguard Worker       if (da->device == db->device) {
136*da0073e9SAndroid Build Coastguard Worker         Py_RETURN_FALSE;
137*da0073e9SAndroid Build Coastguard Worker       } else {
138*da0073e9SAndroid Build Coastguard Worker         Py_RETURN_TRUE;
139*da0073e9SAndroid Build Coastguard Worker       }
140*da0073e9SAndroid Build Coastguard Worker     case Py_LT:
141*da0073e9SAndroid Build Coastguard Worker     case Py_LE:
142*da0073e9SAndroid Build Coastguard Worker     case Py_GT:
143*da0073e9SAndroid Build Coastguard Worker     case Py_GE:
144*da0073e9SAndroid Build Coastguard Worker       throw torch::TypeError("comparison not implemented");
145*da0073e9SAndroid Build Coastguard Worker     default:
146*da0073e9SAndroid Build Coastguard Worker       throw torch::TypeError("unexpected comparison op");
147*da0073e9SAndroid Build Coastguard Worker   }
148*da0073e9SAndroid Build Coastguard Worker   END_HANDLE_TH_ERRORS
149*da0073e9SAndroid Build Coastguard Worker }
150*da0073e9SAndroid Build Coastguard Worker 
THPDevice_reduce(PyObject * _self,PyObject * noargs)151*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_reduce(PyObject* _self, PyObject* noargs) {
152*da0073e9SAndroid Build Coastguard Worker   HANDLE_TH_ERRORS
153*da0073e9SAndroid Build Coastguard Worker   auto self = (THPDevice*)_self;
154*da0073e9SAndroid Build Coastguard Worker   auto ret = THPObjectPtr{PyTuple_New(2)};
155*da0073e9SAndroid Build Coastguard Worker   if (!ret)
156*da0073e9SAndroid Build Coastguard Worker     throw python_error();
157*da0073e9SAndroid Build Coastguard Worker 
158*da0073e9SAndroid Build Coastguard Worker   py::object torch_module = py::module::import("torch");
159*da0073e9SAndroid Build Coastguard Worker   py::object torch_device = torch_module.attr("device");
160*da0073e9SAndroid Build Coastguard Worker   PyTuple_SET_ITEM(ret.get(), 0, torch_device.release().ptr());
161*da0073e9SAndroid Build Coastguard Worker 
162*da0073e9SAndroid Build Coastguard Worker   THPObjectPtr args;
163*da0073e9SAndroid Build Coastguard Worker   std::ostringstream oss;
164*da0073e9SAndroid Build Coastguard Worker   oss << self->device.type();
165*da0073e9SAndroid Build Coastguard Worker   if (self->device.has_index()) {
166*da0073e9SAndroid Build Coastguard Worker     args = THPObjectPtr{Py_BuildValue(
167*da0073e9SAndroid Build Coastguard Worker         "(si)", oss.str().c_str(), static_cast<int>(self->device.index()))};
168*da0073e9SAndroid Build Coastguard Worker   } else {
169*da0073e9SAndroid Build Coastguard Worker     args = THPObjectPtr{Py_BuildValue("(s)", oss.str().c_str())};
170*da0073e9SAndroid Build Coastguard Worker   }
171*da0073e9SAndroid Build Coastguard Worker   if (!args)
172*da0073e9SAndroid Build Coastguard Worker     throw python_error();
173*da0073e9SAndroid Build Coastguard Worker   PyTuple_SET_ITEM(ret.get(), 1, args.release());
174*da0073e9SAndroid Build Coastguard Worker 
175*da0073e9SAndroid Build Coastguard Worker   return ret.release();
176*da0073e9SAndroid Build Coastguard Worker   END_HANDLE_TH_ERRORS
177*da0073e9SAndroid Build Coastguard Worker }
178*da0073e9SAndroid Build Coastguard Worker 
THPDevice_enter(PyObject * self,PyObject * noargs)179*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_enter(PyObject* self, PyObject* noargs) {
180*da0073e9SAndroid Build Coastguard Worker   HANDLE_TH_ERRORS
181*da0073e9SAndroid Build Coastguard Worker   py::object mode = py::module::import("torch.utils._device")
182*da0073e9SAndroid Build Coastguard Worker                         .attr("DeviceContext")(py::handle(self));
183*da0073e9SAndroid Build Coastguard Worker   at::impl::PythonTorchFunctionTLS::push_onto_stack(
184*da0073e9SAndroid Build Coastguard Worker       std::make_shared<c10::SafePyObject>(
185*da0073e9SAndroid Build Coastguard Worker           mode.release().ptr(), getPyInterpreter()));
186*da0073e9SAndroid Build Coastguard Worker   // So that with torch.device('cuda') as dev: works
187*da0073e9SAndroid Build Coastguard Worker   Py_INCREF(self);
188*da0073e9SAndroid Build Coastguard Worker   return self;
189*da0073e9SAndroid Build Coastguard Worker   END_HANDLE_TH_ERRORS
190*da0073e9SAndroid Build Coastguard Worker }
191*da0073e9SAndroid Build Coastguard Worker 
THPDevice_exit(PyObject * self,PyObject * unused)192*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_exit(PyObject* self, PyObject* unused) {
193*da0073e9SAndroid Build Coastguard Worker   HANDLE_TH_ERRORS
194*da0073e9SAndroid Build Coastguard Worker   at::impl::PythonTorchFunctionTLS::pop_stack();
195*da0073e9SAndroid Build Coastguard Worker   Py_RETURN_NONE;
196*da0073e9SAndroid Build Coastguard Worker   END_HANDLE_TH_ERRORS
197*da0073e9SAndroid Build Coastguard Worker }
198*da0073e9SAndroid Build Coastguard Worker 
THPDevice_call(PyObject * self,PyObject * args,PyObject * kwargs)199*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_call(PyObject* self, PyObject* args, PyObject* kwargs) {
200*da0073e9SAndroid Build Coastguard Worker   HANDLE_TH_ERRORS
201*da0073e9SAndroid Build Coastguard Worker   py::object deco =
202*da0073e9SAndroid Build Coastguard Worker       py::module::import("torch.utils._device").attr("device_decorator");
203*da0073e9SAndroid Build Coastguard Worker   return deco(py::handle(self), *py::handle(args), **py::handle(kwargs))
204*da0073e9SAndroid Build Coastguard Worker       .release()
205*da0073e9SAndroid Build Coastguard Worker       .ptr();
206*da0073e9SAndroid Build Coastguard Worker   END_HANDLE_TH_ERRORS
207*da0073e9SAndroid Build Coastguard Worker }
208*da0073e9SAndroid Build Coastguard Worker 
209*da0073e9SAndroid Build Coastguard Worker typedef PyObject* (*getter)(PyObject*, void*);
210*da0073e9SAndroid Build Coastguard Worker 
211*da0073e9SAndroid Build Coastguard Worker // NB: If you edit these properties/methods, update torch/_C/__init__.pyi.in
212*da0073e9SAndroid Build Coastguard Worker 
213*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,cppcoreguidelines-avoid-non-const-global-variables,modernize-avoid-c-arrays)
214*da0073e9SAndroid Build Coastguard Worker static struct PyGetSetDef THPDevice_properties[] = {
215*da0073e9SAndroid Build Coastguard Worker     {"type", (getter)THPDevice_type, nullptr, nullptr, nullptr},
216*da0073e9SAndroid Build Coastguard Worker     {"index", (getter)THPDevice_index, nullptr, nullptr, nullptr},
217*da0073e9SAndroid Build Coastguard Worker     {nullptr}};
218*da0073e9SAndroid Build Coastguard Worker 
219*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,cppcoreguidelines-avoid-non-const-global-variables,modernize-avoid-c-arrays)
220*da0073e9SAndroid Build Coastguard Worker static PyMethodDef THPDevice_methods[] = {
221*da0073e9SAndroid Build Coastguard Worker     {"__reduce__", THPDevice_reduce, METH_NOARGS, nullptr},
222*da0073e9SAndroid Build Coastguard Worker     {"__enter__", THPDevice_enter, METH_NOARGS, nullptr},
223*da0073e9SAndroid Build Coastguard Worker     {"__exit__", THPDevice_exit, METH_VARARGS, nullptr},
224*da0073e9SAndroid Build Coastguard Worker     {nullptr} /* Sentinel */
225*da0073e9SAndroid Build Coastguard Worker };
226*da0073e9SAndroid Build Coastguard Worker 
227*da0073e9SAndroid Build Coastguard Worker PyTypeObject THPDeviceType = {
228*da0073e9SAndroid Build Coastguard Worker     PyVarObject_HEAD_INIT(nullptr, 0) "torch.device", /* tp_name */
229*da0073e9SAndroid Build Coastguard Worker     sizeof(THPDevice), /* tp_basicsize */
230*da0073e9SAndroid Build Coastguard Worker     0, /* tp_itemsize */
231*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_dealloc */
232*da0073e9SAndroid Build Coastguard Worker     0, /* tp_vectorcall_offset */
233*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_getattr */
234*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_setattr */
235*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_reserved */
236*da0073e9SAndroid Build Coastguard Worker     (reprfunc)THPDevice_repr, /* tp_repr */
237*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_as_number */
238*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_as_sequence */
239*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_as_mapping */
240*da0073e9SAndroid Build Coastguard Worker     (hashfunc)THPDevice_hash, /* tp_hash  */
241*da0073e9SAndroid Build Coastguard Worker     // TODO: We're not sure if this is a good idea or not, because making
242*da0073e9SAndroid Build Coastguard Worker     // torch.device callable means that it will start returning true
243*da0073e9SAndroid Build Coastguard Worker     // for callable() queries, and that is unexpected.  We can always add
244*da0073e9SAndroid Build Coastguard Worker     // this later, so for now, don't actually implement this
245*da0073e9SAndroid Build Coastguard Worker     // THPDevice_call, /* tp_call */
246*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_call */
247*da0073e9SAndroid Build Coastguard Worker     (reprfunc)THPDevice_str, /* tp_str */
248*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_getattro */
249*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_setattro */
250*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_as_buffer */
251*da0073e9SAndroid Build Coastguard Worker     Py_TPFLAGS_DEFAULT, /* tp_flags */
252*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_doc */
253*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_traverse */
254*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_clear */
255*da0073e9SAndroid Build Coastguard Worker     (richcmpfunc)THPDevice_rc, /* tp_richcompare */
256*da0073e9SAndroid Build Coastguard Worker     0, /* tp_weaklistoffset */
257*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_iter */
258*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_iternext */
259*da0073e9SAndroid Build Coastguard Worker     THPDevice_methods, /* tp_methods */
260*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_members */
261*da0073e9SAndroid Build Coastguard Worker     THPDevice_properties, /* tp_getset */
262*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_base */
263*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_dict */
264*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_descr_get */
265*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_descr_set */
266*da0073e9SAndroid Build Coastguard Worker     0, /* tp_dictoffset */
267*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_init */
268*da0073e9SAndroid Build Coastguard Worker     nullptr, /* tp_alloc */
269*da0073e9SAndroid Build Coastguard Worker     THPDevice_pynew, /* tp_new */
270*da0073e9SAndroid Build Coastguard Worker };
271*da0073e9SAndroid Build Coastguard Worker 
THPDevice_init(PyObject * module)272*da0073e9SAndroid Build Coastguard Worker void THPDevice_init(PyObject* module) {
273*da0073e9SAndroid Build Coastguard Worker   if (PyType_Ready(&THPDeviceType) < 0) {
274*da0073e9SAndroid Build Coastguard Worker     throw python_error();
275*da0073e9SAndroid Build Coastguard Worker   }
276*da0073e9SAndroid Build Coastguard Worker   Py_INCREF(&THPDeviceType);
277*da0073e9SAndroid Build Coastguard Worker   THPUpperModuleOfDevice = module;
278*da0073e9SAndroid Build Coastguard Worker   if (PyModule_AddObject(module, "device", (PyObject*)&THPDeviceType) != 0) {
279*da0073e9SAndroid Build Coastguard Worker     throw python_error();
280*da0073e9SAndroid Build Coastguard Worker   }
281*da0073e9SAndroid Build Coastguard Worker }
282