| 1224 | |
| 1225 | template <typename Backend> |
| 1226 | void CheckDLPackDeviceBeforeCapsule(py::object obj, size_t idx, |
| 1227 | int &expected_device_id, |
| 1228 | AccessOrder ©_order) { |
| 1229 | if (!py::hasattr(obj, "__dlpack__")) { |
| 1230 | throw py::type_error(make_string( |
| 1231 | "Object at position ", idx, " does not support the DLPack protocol.")); |
| 1232 | } |
| 1233 | if (!py::hasattr(obj, "__dlpack_device__")) { |
| 1234 | return; |
| 1235 | } |
| 1236 | |
| 1237 | py::tuple dev_info = obj.attr("__dlpack_device__")(); |
| 1238 | int dev_type = dev_info[0].cast<int>(); |
| 1239 | if constexpr (std::is_same_v<Backend, CPUBackend>) { |
| 1240 | (void)expected_device_id; |
| 1241 | (void)copy_order; |
| 1242 | if (dev_type != kDLCPU && dev_type != kDLCUDAHost) { |
| 1243 | throw py::value_error(make_string( |
| 1244 | "All tensors must reside in CPU memory. " |
| 1245 | "Tensor at position ", idx, " has DLPack device type ", dev_type, ".")); |
| 1246 | } |
| 1247 | } else { |
| 1248 | if (dev_type != kDLCUDA) { |
| 1249 | throw py::value_error(make_string( |
| 1250 | "All tensors must reside in GPU memory. " |
| 1251 | "Tensor at position ", idx, " has DLPack device type ", dev_type, ".")); |
| 1252 | } |
| 1253 | int dev_id = dev_info[1].cast<int>(); |
| 1254 | if (expected_device_id == -1) { |
| 1255 | expected_device_id = dev_id; |
| 1256 | // When no explicit stream was given, look up the UserStream for this device |
| 1257 | // so every __dlpack__() call below uses the same concrete stream handle. |
| 1258 | if (copy_order == AccessOrder::host()) { |
| 1259 | copy_order = AccessOrder(UserStream::Get()->GetStream( |
| 1260 | static_cast<size_t>(expected_device_id))); |
| 1261 | } |
| 1262 | } else if (dev_id != expected_device_id) { |
| 1263 | throw py::value_error(make_string( |
| 1264 | "All tensors must reside on the same GPU device. " |
| 1265 | "Tensor at position ", idx, " is on GPU ", dev_id, |
| 1266 | " but expected GPU ", expected_device_id, ".")); |
| 1267 | } |
| 1268 | } |
| 1269 | } |
| 1270 | |
| 1271 | template <typename Backend> |
| 1272 | py::capsule GetDLPackCapsule(py::object obj, py::object stream_handle) { |
nothing calls this directly
no test coverage detected