| 733 | } |
| 734 | |
| 735 | Maybe<Tensor> Transpose(const std::shared_ptr<Tensor>& input, const std::vector<int32_t>& permute) { |
| 736 | const auto& shape = input->shape(); |
| 737 | const auto& strides = JUST(input->stride()); |
| 738 | const int64_t ndim = shape->NumAxes(); |
| 739 | int64_t storage_offset = JUST(JUST(input->AsLocalTensor())->storage_offset()); |
| 740 | |
| 741 | CHECK_EQ_OR_RETURN(permute.size(), ndim) |
| 742 | << "permute size should be equal to input tensor's ndim, but got " << permute.size(); |
| 743 | auto positive_perm = permute; |
| 744 | for (auto i = 0; i < positive_perm.size(); i++) { |
| 745 | positive_perm[i] = JUST(maybe_wrap_dim(positive_perm[i], ndim)); |
| 746 | } |
| 747 | |
| 748 | DimVector target_dims(ndim); |
| 749 | Stride stride(ndim); |
| 750 | for (int i = 0; i < ndim; ++i) { |
| 751 | target_dims[i] = shape->At(permute[i]); |
| 752 | stride[i] = strides->at(permute[i]); |
| 753 | } |
| 754 | |
| 755 | auto output = JUST(BasicView(input, Shape(target_dims), stride, storage_offset)); |
| 756 | if (autograd::GradMode::is_enabled() && input->requires_grad()) { |
| 757 | auto backward_fn = std::make_shared<BackwardFunction>(); |
| 758 | backward_fn->body = [=](const TensorTuple& out_grads, TensorTuple* in_grads, |
| 759 | bool create_graph) -> Maybe<void> { |
| 760 | std::vector<int32_t> grad_perm; |
| 761 | grad_perm.resize(ndim); |
| 762 | for (int i = 0; i < ndim; ++i) { grad_perm[permute[i]] = i; } |
| 763 | autograd::AutoGradMode mode(create_graph); |
| 764 | CHECK_EQ_OR_RETURN(out_grads.size(), 1) |
| 765 | << "out grad size should be 1, but got " << out_grads.size(); |
| 766 | in_grads->resize(1); |
| 767 | (*in_grads)[0] = JUST(functional::Transpose(out_grads[0], grad_perm)); |
| 768 | return Maybe<void>::Ok(); |
| 769 | }; |
| 770 | backward_fn->status = []() { return true; }; |
| 771 | TensorTuple outputs{output}; |
| 772 | JUST(GetThreadLocalAutogradEngine()->AddNode("view::transpose_backward", backward_fn, {input}, |
| 773 | &outputs)); |
| 774 | } |
| 775 | return output; |
| 776 | } |
| 777 | |
| 778 | Maybe<Tensor> UnfoldTensor(const std::shared_ptr<Tensor>& input, const int32_t dimension, |
| 779 | const int32_t size, const int32_t step) { |
no test coverage detected