  explicit DepthwiseConv2dNativeBackpropFilterOp(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();

    if (std::is_same<T, bfloat16>::value) {
      dtype_ = DT_BFLOAT16;
    } else if (std::is_same<T, Eigen::half>::value) {
      dtype_ = DT_HALF;
    } else if (std::is_same<T, float>::value) {
      dtype_ = DT_FLOAT;
    } else if (std::is_same<T, double>::value) {
      dtype_ = DT_DOUBLE;
    } else {
      LOG(ERROR) << "Only bfloat16, half, float, and double are supported.";
    }
#if CUDNN_VERSION >= 7603
    // Use CuDNN grouped conv (filter gradients) when input/output is
    // float16(half). See cudnn release note 7.6.3. (https://docs.nvidia.com/dee
    // plearning/sdk/cudnn-release-notes/rel_763.html#rel_763)
    //
    // Grouped convolution was added to cuDNN in version 7.0.1 but
    // TensorFlow op-determinism has been added only for cuDNN versions 7.6.3
    // and later intentionally. This is to avoid potential issues with earlier
    // versions of cuDNN.
    use_cudnn_grouped_conv_ = OpDeterminismRequired() || dtype_ == DT_HALF;
#else
    use_cudnn_grouped_conv_ = false;
#endif
  }
  explicit DepthwiseConv2dNativeBackpropFilterOp(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();

    if (std::is_same<T, bfloat16>::value) {
      dtype_ = DT_BFLOAT16;
    } else if (std::is_same<T, Eigen::half>::value) {
      dtype_ = DT_HALF;
    } else if (std::is_same<T, float>::value) {
      dtype_ = DT_FLOAT;
    } else if (std::is_same<T, double>::value) {
      dtype_ = DT_DOUBLE;
    } else {
      LOG(ERROR) << "Only bfloat16, half, float, and double are supported.";
    }
#if CUDNN_VERSION >= 7603
     
     
     
     
     
     
     
     
    use_cudnn_grouped_conv_ = OpDeterminismRequired() || dtype_ == DT_HALF;
#else
    use_cudnn_grouped_conv_ = false;
#endif
  }