| 349 | } |
| 350 | |
| 351 | Maybe<void> InplaceSqueeze(const std::shared_ptr<Tensor>& input, |
| 352 | const std::vector<int32_t>& squeeze_dims) { |
| 353 | const auto& shape = input->shape(); |
| 354 | const auto& strides = JUST(input->stride()); |
| 355 | const int64_t ndim = shape->NumAxes(); |
| 356 | |
| 357 | const int target_ndim = ndim - squeeze_dims.size(); |
| 358 | DimVector target_dim_vec(target_ndim); |
| 359 | Stride target_stride_vec(target_ndim); |
| 360 | |
| 361 | { |
| 362 | int cnt = 0; |
| 363 | for (int i = 0; i < ndim; i++) { |
| 364 | if (find(squeeze_dims.begin(), squeeze_dims.end(), i) == squeeze_dims.end()) { |
| 365 | target_dim_vec[cnt] = shape->At(i); |
| 366 | target_stride_vec[cnt] = strides->at(i); |
| 367 | cnt++; |
| 368 | } |
| 369 | } |
| 370 | } |
| 371 | |
| 372 | int64_t storage_offset = JUST(JUST(input->AsLocalTensor())->storage_offset()); |
| 373 | JUST(view::InplaceView(input, Shape(target_dim_vec), target_stride_vec, storage_offset)); |
| 374 | |
| 375 | if (autograd::GradMode::is_enabled() && input->requires_grad()) { |
| 376 | auto backward_fn = std::make_shared<BackwardFunction>(); |
| 377 | backward_fn->body = [=](const TensorTuple& out_grads, TensorTuple* in_grads, |
| 378 | bool create_graph) -> Maybe<void> { |
| 379 | autograd::AutoGradMode mode(create_graph); |
| 380 | CHECK_EQ_OR_RETURN(out_grads.size(), 1); // NOLINT(maybe-need-error-msg) |
| 381 | in_grads->resize(1); |
| 382 | JUST(oneflow::VectorAt(*in_grads, 0)) = JUST(functional::Reshape( |
| 383 | JUST(oneflow::VectorAt(out_grads, 0)), Shape(input->shape()->dim_vec()))); |
| 384 | return Maybe<void>::Ok(); |
| 385 | }; |
| 386 | backward_fn->status = []() { return true; }; |
| 387 | TensorTuple outputs{input}; |
| 388 | JUST(GetThreadLocalAutogradEngine()->AddNode("view::inplace_squeeze_backward", backward_fn, |
| 389 | {input}, &outputs)); |
| 390 | } |
| 391 | return Maybe<void>::Ok(); |
| 392 | } |
| 393 | |
| 394 | Maybe<Tensor> Expand(const std::shared_ptr<Tensor>& input, const Shape& expand_shape) { |
| 395 | const Shape& input_shape = *input->shape(); |
no test coverage detected