| 1438 | |
| 1439 | template <typename Backend> |
| 1440 | std::shared_ptr<TensorList<Backend>> TensorListFromListOfTensors( |
| 1441 | py::list &list_of_tensors, |
| 1442 | const std::optional<std::string> &layout = {}, |
| 1443 | bool contiguous = true) { |
| 1444 | constexpr uint32_t rangeColor = |
| 1445 | std::is_same_v<Backend, CPUBackend> ? kCPUTensorColor : kGPUTensorColor; |
| 1446 | DomainTimeRange range("TensorListFromListOfTensors", rangeColor); |
| 1447 | if (list_of_tensors.empty()) { |
| 1448 | auto ptr = std::make_shared<TensorList<Backend>>(); |
| 1449 | if (layout.has_value()) { |
| 1450 | ptr->set_sample_dim(layout->length()); |
| 1451 | ptr->SetLayout(*layout); |
| 1452 | } |
| 1453 | return ptr; |
| 1454 | } |
| 1455 | |
| 1456 | std::optional<TensorList<Backend>> non_contiguous_tmp; |
| 1457 | std::shared_ptr<TensorList<Backend>> non_contiguous_out; |
| 1458 | |
| 1459 | if (contiguous) |
| 1460 | non_contiguous_tmp = TensorList<Backend>(list_of_tensors.size()); |
| 1461 | else |
| 1462 | non_contiguous_out = std::make_shared<TensorList<Backend>>(list_of_tensors.size()); |
| 1463 | |
| 1464 | TensorList<Backend> &non_contiguous = contiguous |
| 1465 | ? non_contiguous_tmp.value() |
| 1466 | : *non_contiguous_out; |
| 1467 | |
| 1468 | int expected_type = -2; |
| 1469 | int expected_device_id = -1; |
| 1470 | |
| 1471 | AccessOrder copy_order = AccessOrder::host(); |
| 1472 | |
| 1473 | { |
| 1474 | DomainTimeRange range("Build initial list", rangeColor); |
| 1475 | |
| 1476 | for (size_t i = 0; i < list_of_tensors.size(); ++i) { |
| 1477 | try { |
| 1478 | auto &t = list_of_tensors[i].cast<Tensor<Backend> &>(); |
| 1479 | if (i == 0) { |
| 1480 | non_contiguous.SetupLike(t); |
| 1481 | if constexpr (std::is_same_v<Backend, GPUBackend>) { |
| 1482 | copy_order = AccessOrder(UserStream::Get()->GetStream(t)); |
| 1483 | expected_device_id = t.device_id(); |
| 1484 | } |
| 1485 | } |
| 1486 | DALIDataType cur_type = t.type(); |
| 1487 | |
| 1488 | if (expected_type == -2) { |
| 1489 | expected_type = t.type(); |
| 1490 | } else if (expected_type != cur_type) { |
| 1491 | throw py::type_error(make_string( |
| 1492 | "Tensors cannot have different data types. Tensor at position ", i, " has type '", |
| 1493 | cur_type, "' expected to have type '", DALIDataType(expected_type), "'.")); |
| 1494 | } |
| 1495 | if constexpr (std::is_same_v<Backend, GPUBackend>) { |
| 1496 | if (t.device_id() != expected_device_id) { |
| 1497 | throw py::value_error(make_string( |
nothing calls this directly
no test coverage detected