| 513 | } |
| 514 | |
| 515 | Maybe<Tensor> Narrow(const std::shared_ptr<Tensor>& input, const int64_t dim, const int64_t start, |
| 516 | const int64_t length) { |
| 517 | const auto& shape = input->shape(); |
| 518 | const auto& strides = JUST(input->stride()); |
| 519 | const int64_t ndim = shape->NumAxes(); |
| 520 | DimVector dim_vec; |
| 521 | dim_vec.insert(dim_vec.end(), shape->dim_vec().cbegin(), shape->dim_vec().cbegin() + dim); |
| 522 | dim_vec.insert(dim_vec.end(), length); |
| 523 | dim_vec.insert(dim_vec.end(), shape->dim_vec().cbegin() + dim + 1, shape->dim_vec().end()); |
| 524 | |
| 525 | int64_t storage_offset = JUST(JUST(input->AsLocalTensor())->storage_offset()); |
| 526 | Shape target_shape(dim_vec); |
| 527 | |
| 528 | Stride stride(ndim); |
| 529 | for (int i = 0; i < ndim; ++i) { |
| 530 | stride[i] = strides->at(i); |
| 531 | if (dim == i) { storage_offset += start * strides->at(i); } |
| 532 | } |
| 533 | |
| 534 | auto output = JUST(BasicView(input, target_shape, stride, storage_offset)); |
| 535 | if (autograd::GradMode::is_enabled() && input->requires_grad()) { |
| 536 | auto backward_fn = std::make_shared<BackwardFunction>(); |
| 537 | backward_fn->body = [=](const TensorTuple& out_grads, TensorTuple* in_grads, |
| 538 | bool create_graph) -> Maybe<void> { |
| 539 | autograd::AutoGradMode mode(create_graph); |
| 540 | CHECK_EQ_OR_RETURN(out_grads.size(), 1) |
| 541 | << "out grad size should be 1, but got " << out_grads.size(); |
| 542 | auto like = |
| 543 | JUST(functional::Empty(Shape(input->shape()->dim_vec()), input->dtype(), |
| 544 | JUST(input->device()), /*requires_grad=*/input->requires_grad(), |
| 545 | /*pin_memory=*/false)); |
| 546 | in_grads->resize(1); |
| 547 | (*in_grads)[0] = JUST(functional::NarrowGrad(out_grads[0], like, dim, start, length)); |
| 548 | return Maybe<void>::Ok(); |
| 549 | }; |
| 550 | backward_fn->status = []() { return true; }; |
| 551 | TensorTuple outputs{output}; |
| 552 | JUST(GetThreadLocalAutogradEngine()->AddNode("view::narrow_backward", backward_fn, {input}, |
| 553 | &outputs)); |
| 554 | } |
| 555 | return output; |
| 556 | } |
| 557 | |
| 558 | Maybe<Tensor> AsStridedGrad(const std::shared_ptr<one::Tensor>& dy, |
| 559 | const std::shared_ptr<one::Tensor>& input, |
no test coverage detected