| 289 | } // namespace lite |
| 290 | |
| 291 | std::shared_ptr<Tensor> TensorUtils::concat( |
| 292 | const std::vector<Tensor>& tensors, int dim, LiteDeviceType dst_device, |
| 293 | int dst_device_id) { |
| 294 | if (tensors.size() <= 0) { |
| 295 | return std::make_shared<Tensor>(); |
| 296 | } |
| 297 | if (dst_device == LiteDeviceType::LITE_DEVICE_DEFAULT) { |
| 298 | dst_device = tensors.front().get_device_type(); |
| 299 | } |
| 300 | if (dst_device_id == -1) { |
| 301 | dst_device_id = tensors.front().get_device_id(); |
| 302 | } |
| 303 | bool is_pinned_host = tensors.front().is_pinned_host(); |
| 304 | auto layout = tensors.front().get_layout(); |
| 305 | LITE_ASSERT(static_cast<int>(layout.ndim) > dim, "the dim in concat is error."); |
| 306 | size_t sum_in_dim = layout.shapes[dim]; |
| 307 | for (size_t i = 1; i < tensors.size(); ++i) { |
| 308 | auto other_layout = tensors[i].get_layout(); |
| 309 | LITE_ASSERT( |
| 310 | other_layout.ndim == layout.ndim, |
| 311 | "the dim size of tensors is not same!"); |
| 312 | LITE_ASSERT( |
| 313 | other_layout.data_type == layout.data_type, |
| 314 | "the dtype of tensors is not same!"); |
| 315 | for (size_t j = 0; j < other_layout.ndim; ++j) { |
| 316 | if (dim == static_cast<int>(j)) { |
| 317 | sum_in_dim += other_layout.shapes[j]; |
| 318 | continue; |
| 319 | } |
| 320 | LITE_ASSERT( |
| 321 | other_layout.shapes[j] == layout.shapes[j], |
| 322 | "the shape of tensors is not same!"); |
| 323 | } |
| 324 | } |
| 325 | layout.shapes[dim] = sum_in_dim; |
| 326 | auto result = |
| 327 | std::make_shared<Tensor>(dst_device_id, dst_device, layout, is_pinned_host); |
| 328 | size_t index = 0; |
| 329 | std::vector<size_t> start(dim + 1, 0); |
| 330 | std::vector<size_t> end(dim + 1, 0); |
| 331 | for (int i = 0; i < dim; i++) { |
| 332 | end[i] = layout.shapes[i]; |
| 333 | } |
| 334 | for (size_t i = 0; i < tensors.size(); ++i) { |
| 335 | auto&& tensor = tensors[i]; |
| 336 | auto layout = tensor.get_layout(); |
| 337 | if (layout.shapes[dim] == 0) |
| 338 | continue; |
| 339 | start[dim] = index; |
| 340 | end[dim] = index + layout.shapes[dim]; |
| 341 | auto&& sub_dst = result->slice(start, end); |
| 342 | sub_dst->copy_from(tensor); |
| 343 | index += layout.shapes[dim]; |
| 344 | } |
| 345 | return result; |
| 346 | } |
| 347 | |
| 348 | // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}} |