| 784 | |
| 785 | template <typename T> |
| 786 | void LaunchConv2DBackpropInputOp<GPUDevice, T>::operator()( |
| 787 | OpKernelContext* ctx, bool use_cudnn, bool cudnn_use_autotune, |
| 788 | const Tensor& out_backprop, const Tensor& filter, int row_dilation, |
| 789 | int col_dilation, int row_stride, int col_stride, const Padding& padding, |
| 790 | const std::vector<int64>& explicit_paddings, Tensor* in_backprop, |
| 791 | TensorFormat data_format) { |
| 792 | #if GOOGLE_CUDA && CUDNN_VERSION >= 8100 |
| 793 | using se::dnn::ExecutionPlanConfig; |
| 794 | using se::dnn::ExecutionPlanDesc; |
| 795 | using se::dnn::ProfileExecutionPlanResult; |
| 796 | #endif // GOOGLE_CUDA && CUDNN_VERSION >= 8100 |
| 797 | using se::dnn::AlgorithmConfig; |
| 798 | using se::dnn::AlgorithmDesc; |
| 799 | using se::dnn::ProfileResult; |
| 800 | std::vector<int32> strides(4, 1); |
| 801 | std::vector<int32> dilations(4, 1); |
| 802 | auto input_h = GetTensorDimIndex(data_format, 'H'); |
| 803 | auto input_w = GetTensorDimIndex(data_format, 'W'); |
| 804 | strides[input_h] = row_stride; |
| 805 | strides[input_w] = col_stride; |
| 806 | dilations[input_h] = row_dilation; |
| 807 | dilations[input_w] = col_dilation; |
| 808 | TensorShape input_shape = in_backprop->shape(); |
| 809 | |
| 810 | const TensorShape& filter_shape = filter.shape(); |
| 811 | ConvBackpropDimensions dims; |
| 812 | OP_REQUIRES_OK( |
| 813 | ctx, ConvBackpropComputeDimensionsV2( |
| 814 | "Conv2DSlowBackpropInput", /*num_spatial_dims=*/2, input_shape, |
| 815 | filter_shape, out_backprop.shape(), dilations, strides, padding, |
| 816 | explicit_paddings, data_format, &dims)); |
| 817 | |
| 818 | int64 padding_top = -1, padding_bottom = -1; |
| 819 | int64 padding_left = -1, padding_right = -1; |
| 820 | if (padding == EXPLICIT) { |
| 821 | GetExplicitPaddingForDim(explicit_paddings, data_format, 'H', &padding_top, |
| 822 | &padding_bottom); |
| 823 | GetExplicitPaddingForDim(explicit_paddings, data_format, 'W', &padding_left, |
| 824 | &padding_right); |
| 825 | } |
| 826 | int64 expected_out_rows, expected_out_cols; |
| 827 | // The function is guaranteed to succeed because we checked the output and |
| 828 | // padding was valid earlier. |
| 829 | TF_CHECK_OK(GetWindowedOutputSizeVerboseV2( |
| 830 | dims.spatial_dims[0].input_size, dims.spatial_dims[0].filter_size, |
| 831 | row_dilation, row_stride, padding, &expected_out_rows, &padding_top, |
| 832 | &padding_bottom)); |
| 833 | DCHECK_EQ(dims.spatial_dims[0].output_size, expected_out_rows); |
| 834 | TF_CHECK_OK(GetWindowedOutputSizeVerboseV2( |
| 835 | dims.spatial_dims[1].input_size, dims.spatial_dims[1].filter_size, |
| 836 | col_dilation, col_stride, padding, &expected_out_cols, &padding_left, |
| 837 | &padding_right)); |
| 838 | DCHECK_EQ(dims.spatial_dims[1].output_size, expected_out_cols); |
| 839 | |
| 840 | auto* stream = ctx->op_device_context()->stream(); |
| 841 | OP_REQUIRES(ctx, stream, errors::Internal("No GPU stream available.")); |
| 842 | |
| 843 | if (!use_cudnn) { |
nothing calls this directly
no test coverage detected