| 23 | namespace at { |
| 24 | |
| 25 | inline std::vector<at::Tensor> tensor_split(const at::Tensor& self, |
| 26 | int64_t sections, |
| 27 | int64_t dim = 0) { |
| 28 | // Follow PyTorch's tensor_split_sections_symint implementation |
| 29 | PD_CHECK(self._PD_GetInner().dims().size() > 0, |
| 30 | "tensor_split expected at least a 1-dimensional tensor, but got a " |
| 31 | "tensor with ", |
| 32 | self._PD_GetInner().dims().size(), |
| 33 | " dims"); |
| 34 | |
| 35 | PD_CHECK( |
| 36 | sections > 0, "number of sections must be larger than 0, got ", sections); |
| 37 | |
| 38 | int64_t dim_size = self._PD_GetInner().dims()[dim]; |
| 39 | |
| 40 | // Calculate split sizes: first (dim_size % sections) chunks get size |
| 41 | // (dim_size / sections + 1), remaining chunks get size (dim_size / sections) |
| 42 | auto min_split_size = dim_size / sections; |
| 43 | auto num_splits_one_extra = dim_size % sections; |
| 44 | |
| 45 | std::vector<int64_t> split_sizes; |
| 46 | split_sizes.reserve(sections); |
| 47 | |
| 48 | for (int64_t split_idx = 0; split_idx < sections; ++split_idx) { |
| 49 | auto split_size = (split_idx < num_splits_one_extra) ? (min_split_size + 1) |
| 50 | : min_split_size; |
| 51 | split_sizes.push_back(split_size); |
| 52 | } |
| 53 | |
| 54 | // Use split with calculated sizes |
| 55 | auto outputs = |
| 56 | paddle::experimental::split(self._PD_GetInner(), split_sizes, dim); |
| 57 | |
| 58 | std::vector<at::Tensor> at_tensors; |
| 59 | at_tensors.reserve(outputs.size()); |
| 60 | for (const auto& paddle_tensor : outputs) { |
| 61 | at_tensors.emplace_back(paddle_tensor); |
| 62 | } |
| 63 | return at_tensors; |
| 64 | } |
| 65 | |
| 66 | inline std::vector<at::Tensor> tensor_split_symint(const at::Tensor& self, |
| 67 | c10::SymInt sections, |
no test coverage detected