  explicit DepthwiseConv2dNativeBackpropInputOp(OpKernelConstruction* context)
      : OpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("strides", &strides_));
    OP_REQUIRES(context, strides_.size() == 4,
                errors::InvalidArgument("Sliding window strides field must "
                                        "specify 4 dimensions"));

    string data_format;
    OP_REQUIRES_OK(context, context->GetAttr("data_format", &data_format));
    OP_REQUIRES(context, FormatFromString(data_format, &data_format_),
                errors::InvalidArgument("Invalid data format"));

    stride_ = GetTensorDim(strides_, data_format_, 'H');
    const int64_t stride_w = GetTensorDim(strides_, data_format_, 'W');
    const int64_t stride_n = GetTensorDim(strides_, data_format_, 'N');
    const int64_t stride_c = GetTensorDim(strides_, data_format_, 'C');

    OP_REQUIRES(context, stride_ == stride_w,
                errors::InvalidArgument(
                    "Current implementation only supports equal length "
                    "strides in the row and column dimensions."));
    OP_REQUIRES(
        context, (stride_n == 1 && stride_c == 1),
        errors::InvalidArgument("Current implementation does not yet support "
                                "strides in the batch and depth dimensions."));
    OP_REQUIRES_OK(context, context->GetAttr("padding", &padding_));
    OP_REQUIRES_OK(context,
                   context->GetAttr("explicit_paddings", &explicit_paddings_));
    OP_REQUIRES_OK(context, CheckValidPadding(padding_, explicit_paddings_,
                                              /*num_dims=*/4, data_format_));

    cudnn_use_autotune_ = CudnnUseAutotune();
    dtype_ = DataTypeToEnum<T>::value;
#if CUDNN_VERSION >= 8000
    // From the cuDNN release note 8.0: We’ve extended the fprop and dgrad
    // NHWC depthwise kernels to support more combinations (filter
    // sizes/strides) such as 5x5/1x1, 5x5/2x2, 7x7/1x1, 7x7/2x2 (in addition
    // to what we already have, 1x1/1x1, 3x3/1x1, 3x3/2x2), which provides
    // good performance. (https://docs.nvidia.com/deeplearning/sdk/cudnn-
    // release-notes/rel_8.html#rel_8)
    use_cudnn_grouped_conv_ =
        dtype_ == DT_HALF &&
        ((data_format_ == FORMAT_NCHW && stride_ == 1 && stride_w == 1) ||
         (data_format_ == FORMAT_NHWC && stride_ == stride_w &&
          (stride_ == 1 || stride_ == 2)));
#elif CUDNN_VERSION >= 7603
    // Use CuDNN grouped conv (input gradient) when stride = 1, input/output is
    // NCHW and float16(half). See cudnn release note 7.6.3 (https://docs.nvidi
    // a.com/deeplearning/sdk/cudnn-release-notes/rel_763.html#rel_763).
    use_cudnn_grouped_conv_ = dtype_ == DT_HALF &&
                              data_format_ == FORMAT_NCHW && stride_ == 1 &&
                              stride_w == 1;
#else
    use_cudnn_grouped_conv_ = false;
#endif
  }
  explicit DepthwiseConv2dNativeBackpropInputOp(OpKernelConstruction* context)
      : OpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("strides", &strides_));
    OP_REQUIRES(context, strides_.size() == 4,
                errors::InvalidArgument("Sliding window strides field must "
                                        "specify 4 dimensions"));

    string data_format;
    OP_REQUIRES_OK(context, context->GetAttr("data_format", &data_format));
    OP_REQUIRES(context, FormatFromString(data_format, &data_format_),
                errors::InvalidArgument("Invalid data format"));

    stride_ = GetTensorDim(strides_, data_format_, 'H');
    const int64_t stride_w = GetTensorDim(strides_, data_format_, 'W');
    const int64_t stride_n = GetTensorDim(strides_, data_format_, 'N');
    const int64_t stride_c = GetTensorDim(strides_, data_format_, 'C');

    OP_REQUIRES(context, stride_ == stride_w,
                errors::InvalidArgument(
                    "Current implementation only supports equal length "
                    "strides in the row and column dimensions."));
    OP_REQUIRES(
        context, (stride_n == 1 && stride_c == 1),
        errors::InvalidArgument("Current implementation does not yet support "
                                "strides in the batch and depth dimensions."));
    OP_REQUIRES_OK(context, context->GetAttr("padding", &padding_));
    OP_REQUIRES_OK(context,
                   context->GetAttr("explicit_paddings", &explicit_paddings_));
    OP_REQUIRES_OK(context, CheckValidPadding(padding_, explicit_paddings_,
                                               4, data_format_));

    cudnn_use_autotune_ = CudnnUseAutotune();
    dtype_ = DataTypeToEnum<T>::value;
#if CUDNN_VERSION >= 8000
     
     
     
     
     
     
    use_cudnn_grouped_conv_ =
        dtype_ == DT_HALF &&
        ((data_format_ == FORMAT_NCHW && stride_ == 1 && stride_w == 1) ||
         (data_format_ == FORMAT_NHWC && stride_ == stride_w &&
          (stride_ == 1 || stride_ == 2)));
#elif CUDNN_VERSION >= 7603
     
     
     
    use_cudnn_grouped_conv_ = dtype_ == DT_HALF &&
                              data_format_ == FORMAT_NCHW && stride_ == 1 &&
                              stride_w == 1;
#else
    use_cudnn_grouped_conv_ = false;
#endif
  }