c++ infer for conv2dbackpropfilter and conv2dbackpropinput

This commit is contained in:
simson 2021-05-19 16:53:30 +08:00
parent 2a6bf68809
commit c4f918dae4
5 changed files with 77 additions and 106 deletions

View File

@ -1,5 +1,5 @@
/**
* Copyright 2020 Huawei Technologies Co., Ltd
* Copyright 2021 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,20 +27,22 @@ namespace {
abstract::ShapePtr Conv2DBackpropFilterInferShape(const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args) {
MS_EXCEPTION_IF_NULL(primitive);
auto out_put = input_args[2]->BuildValue();
auto infer_shape = GetValue<std::vector<int64_t>>(out_put);
return std::make_shared<abstract::Shape>(infer_shape);
auto prim_name = primitive->name();
// check
auto w_size_v = input_args[2]->BuildValue();
auto ret_shape = CheckAndConvertUtils::CheckAttrIntOrTupleInt("w_size", w_size_v, prim_name);
return std::make_shared<abstract::Shape>(ret_shape);
}
TypePtr Conv2DBackpropFilterInferType(const PrimitivePtr &prim, const std::vector<AbstractBasePtr> &input_args) {
for (const auto &item : input_args) {
MS_EXCEPTION_IF_NULL(item);
}
const std::set<TypePtr> valid_types = {kInt8, kInt32, kFloat16, kFloat32};
MS_EXCEPTION_IF_NULL(prim);
auto prim_name = prim->name();
// check
std::map<std::string, TypePtr> types;
types.emplace("drotput", input_args[0]->BuildType());
types.emplace("input_x", input_args[1]->BuildType());
return CheckAndConvertUtils::CheckTensorTypeSame(types, valid_types, prim->name());
types.emplace("doutput", input_args[0]->BuildType());
types.emplace("x", input_args[1]->BuildType());
std::set<TypePtr> valid_x_type = {kInt8, kInt32, kFloat16, kFloat32};
return CheckAndConvertUtils::CheckTensorTypeSame(types, valid_x_type, prim_name);
}
} // namespace
@ -142,9 +144,17 @@ Format Conv2DBackpropFilter::get_format() const {
AbstractBasePtr Conv2DBackpropFilterInfer(const abstract::AnalysisEnginePtr &, const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args) {
MS_EXCEPTION_IF_NULL(primitive);
auto prim_name = primitive->name();
// check
CheckAndConvertUtils::CheckInteger("input size", input_args.size(), kGreaterEqual, 3, prim_name);
for (const auto &item : input_args) {
MS_EXCEPTION_IF_NULL(item);
}
return std::make_shared<abstract::AbstractTensor>(Conv2DBackpropFilterInferType(primitive, input_args),
Conv2DBackpropFilterInferShape(primitive, input_args)->shape());
}
REGISTER_PRIMITIVE_C(kNameConv2DBackpropFilter, Conv2DBackpropFilter);
REGISTER_PRIMITIVE_EVAL_IMPL(Conv2DBackpropFilter, prim::kPrimConv2DBackpropFilter, Conv2DBackpropFilterInfer, nullptr,
true);
} // namespace ops
} // namespace mindspore

View File

@ -1,5 +1,5 @@
/**
* Copyright 2020 Huawei Technologies Co., Ltd
* Copyright 2021 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,18 +23,25 @@
namespace mindspore {
namespace ops {
namespace {
void SetPadList(const PrimitivePtr &primitive, const std::vector<int64_t> &dout_shape_norm,
const std::vector<int64_t> &x_size_v) {
auto kernel_size = GetValue<std::vector<int64_t>>(primitive->GetAttr(kKernelSize));
auto stride = GetValue<std::vector<int64_t>>(primitive->GetAttr(kStride));
auto dilation = GetValue<std::vector<int64_t>>(primitive->GetAttr(kStride));
auto pad_list = GetValue<std::vector<int64_t>>(primitive->GetAttr(kPadList));
auto pad_mode = PadMode(GetValue<int64_t>(primitive->GetAttr(kPadMode)));
if (std::all_of(pad_list.begin(), pad_list.end(), [](int64_t elem) -> bool { return elem != 0; })) {
primitive->AddAttr(kPadList, MakeValue(pad_list));
MS_EXCEPTION_IF_NULL(primitive);
auto prim_name = primitive->name();
// check
auto kernel_size =
CheckAndConvertUtils::CheckAttrIntOrTupleInt("kernel_size", primitive->GetAttr(kKernelSize), prim_name);
auto stride = CheckAndConvertUtils::CheckAttrIntOrTupleInt("stride", primitive->GetAttr(kStride), prim_name);
auto dilation = CheckAndConvertUtils::CheckAttrIntOrTupleInt("dilation", primitive->GetAttr(kDilation), prim_name);
// default pad mode is valid
auto attr_pad_list_prt = primitive->GetAttr(kPadList);
auto pad_mode = GetValue<int64_t>(primitive->GetAttr(kPadMode));
ShapeVector pad_list = {0, 0, 0, 0};
if (!attr_pad_list_prt->isa<None>()) {
pad_list = GetValue<ShapeVector>(attr_pad_list_prt);
} else if (pad_mode == SAME) {
auto stride_h = stride[0];
auto stride_w = stride[1];
auto stride_h = stride[2];
auto stride_w = stride[3];
auto kernel_h = kernel_size[0];
auto kernel_w = kernel_size[1];
auto dilation_h = dilation[2];
@ -43,7 +50,7 @@ void SetPadList(const PrimitivePtr &primitive, const std::vector<int64_t> &dout_
pad_needed_h = 0 > pad_needed_h ? 0 : pad_needed_h;
auto pad_top = pad_needed_h / 2;
auto pad_bottom = pad_needed_h - pad_top;
auto pad_needed_w = (dout_shape_norm[3] - 1) * stride_w + dilation_w * (kernel_w - 1) + 1 - x_size_v[2];
auto pad_needed_w = (dout_shape_norm[3] - 1) * stride_w + dilation_w * (kernel_w - 1) + 1 - x_size_v[3];
pad_needed_w = pad_needed_w > 0L ? pad_needed_w : 0L;
auto pad_left = pad_needed_w / 2;
auto pad_right = pad_needed_w - pad_left;
@ -53,34 +60,44 @@ void SetPadList(const PrimitivePtr &primitive, const std::vector<int64_t> &dout_
}
primitive->AddAttr(kPadList, MakeValue(pad_list));
}
abstract::ShapePtr Conv2DBackpropInputInferShape(const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args) {
MS_EXCEPTION_IF_NULL(primitive);
auto prim_name = primitive->name();
auto x_size_v = input_args[2]->BuildValue();
auto ret_shape = CheckAndConvertUtils::CheckAttrIntOrTupleInt("x_size", x_size_v, prim_name);
auto dout_shape = CheckAndConvertUtils::ConvertShapePtrToShapeMap(input_args[0]->BuildShape())[kShape];
auto format = CheckAndConvertUtils::GetAndCheckFormat(primitive->GetAttr(kFormat));
ShapeVector tmp_shape = {dout_shape[0], dout_shape[2], dout_shape[3], dout_shape[1]};
auto dout_shape_norm = format == Format::NCHW ? dout_shape : tmp_shape;
SetPadList(primitive, dout_shape_norm, ret_shape);
return std::make_shared<abstract::Shape>(ret_shape);
}
TypePtr Conv2DBackpropInputInferType(const PrimitivePtr &prim, const std::vector<AbstractBasePtr> &input_args) {
MS_EXCEPTION_IF_NULL(prim);
auto prim_name = prim->name();
// check
std::map<std::string, TypePtr> types;
types.emplace("doutput", input_args[0]->BuildType());
types.emplace("w", input_args[1]->BuildType());
std::set<TypePtr> valid_x_type = {kInt8, kInt32, kFloat16, kFloat32};
return CheckAndConvertUtils::CheckTensorTypeSame(types, valid_x_type, prim_name);
}
} // namespace
AbstractBasePtr Conv2DBackpropInputInfer(const abstract::AnalysisEnginePtr &, const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args) {
MS_EXCEPTION_IF_NULL(primitive);
auto prim_name = primitive->name();
CheckAndConvertUtils::CheckInteger("input number", input_args.size(), kEqual, 3, prim_name);
// check
CheckAndConvertUtils::CheckInteger("input size", input_args.size(), kGreaterEqual, 3, prim_name);
for (const auto &item : input_args) {
MS_EXCEPTION_IF_NULL(item);
}
auto doutput = input_args[0];
auto x_size = input_args[2];
auto x_size_value = x_size->GetValueTrack();
MS_EXCEPTION_IF_NULL(x_size);
auto x_size_v = GetValue<std::vector<int64_t>>(x_size_value);
// infer dtype
auto dtype = doutput->BuildType();
if (!dtype->isa<TensorType>()) {
MS_LOG(EXCEPTION) << "Conv2DBackpropInputInfer doutput must be tensor but got" << dtype->ToString();
}
auto input_tensor_type = dtype->cast<TensorTypePtr>();
MS_EXCEPTION_IF_NULL(input_tensor_type);
auto element = input_tensor_type->element();
// infer shape
auto dout_shape = doutput->BuildShape();
MS_EXCEPTION_IF_NULL(doutput);
auto dout_shapeptr = dout_shape->cast<abstract::ShapePtr>();
auto dout_shape_norm = dout_shapeptr->shape();
SetPadList(primitive, dout_shape_norm, x_size_v);
return std::make_shared<abstract::AbstractTensor>(element, std::make_shared<abstract::Shape>(x_size_v));
auto abs = std::make_shared<abstract::AbstractTensor>(Conv2DBackpropInputInferType(primitive, input_args),
Conv2DBackpropInputInferShape(primitive, input_args));
return abs;
}
void Conv2DBackpropInput::Init(int64_t out_channel, const std::vector<int64_t> &kernel_size, int64_t mode,
@ -200,6 +217,7 @@ std::vector<int64_t> Conv2DBackpropInput::get_pad_list() const {
auto value_ptr = GetAttr(kPadList);
return GetValue<std::vector<int64_t>>(value_ptr);
}
REGISTER_PRIMITIVE_C(kNameConv2DBackpropInput, Conv2DBackpropInput);
REGISTER_PRIMITIVE_EVAL_IMPL(Conv2DBackpropInput, prim::kPrimConv2DBackpropInput, Conv2DBackpropInputInfer, nullptr,
true);
} // namespace ops
} // namespace mindspore

View File

@ -603,7 +603,7 @@ void CheckAndConvertUtils::CheckMode(const std::string &class_name) {
auto ms_context = MsContext::GetInstance();
MS_EXCEPTION_IF_NULL(ms_context);
if (ms_context->get_param<int>(MS_CTX_EXECUTION_MODE) == kPynativeMode) {
MS_EXCEPTION(NotSupportError) << class_name << "operator does not support PyNative mode.";
MS_EXCEPTION(NotSupportError) << class_name << " operator does not support PyNative mode.";
}
}

View File

@ -447,7 +447,7 @@ class Conv3DBackpropFilter(PrimitiveWithInfer):
return out
class Conv2DBackpropFilter(PrimitiveWithInfer):
class Conv2DBackpropFilter(Primitive):
"""
Computes the gradients of convolution with respect to the filter.
@ -506,21 +506,6 @@ class Conv2DBackpropFilter(PrimitiveWithInfer):
raise ValueError("NHWC format only support in GPU target.")
self.add_prim_attr('data_format', self.format)
def __infer__(self, doutput, x, w_size):
w_size_v = w_size['value']
validator.check_value_type('w_size', w_size_v, [tuple], self.name)
for i, dim_len in enumerate(w_size_v):
validator.check_value_type("w_size[%d]" % i, dim_len, [int], self.name)
args = {"x": x['dtype'], "doutput": doutput['dtype']}
validator.check_tensors_dtypes_same_and_valid(args, [mstype.int8, mstype.int32, mstype.float16, mstype.float32],
self.name)
out = {
'value': None,
'shape': w_size_v,
'dtype': doutput['dtype'],
}
return out
class DepthwiseConv2dNativeBackpropFilter(PrimitiveWithInfer):
"""

View File

@ -1257,7 +1257,7 @@ class BatchNorm(PrimitiveWithInfer):
return (input_x, mstype.float32, mstype.float32, mstype.float32, mstype.float32)
class Conv2D(PrimitiveWithCheck):
class Conv2D(Primitive):
r"""
2D convolution layer.
@ -1918,7 +1918,7 @@ class AvgPool(_Pool):
super(AvgPool, self).__init__(kernel_size, strides, pad_mode, data_format)
class Conv2DBackpropInput(PrimitiveWithInfer):
class Conv2DBackpropInput(Primitive):
"""
Computes the gradients of convolution with respect to the input.
@ -2026,48 +2026,6 @@ class Conv2DBackpropInput(PrimitiveWithInfer):
validator.check_non_negative_int(x, 'element of pad_list', self.name)
self.pad_list = pad_list
def __infer__(self, doutput, w, x_size):
x_size_v = x_size['value']
validator.check_value_type('x_size', x_size_v, [tuple], self.name)
for i, dim_len in enumerate(x_size_v):
validator.check_value_type("x_size[%d]" % i, dim_len, [int], self.name)
args = {'doutput': doutput['dtype'], 'w': w['dtype']}
valid_dtypes = [mstype.int8, mstype.int32, mstype.float16, mstype.float32]
validator.check_tensors_dtypes_same_and_valid(args, valid_dtypes, self.name)
# infer shape
dout_shape = doutput['shape']
dout_shape_norm = dout_shape if self.format == "NCHW" else \
[dout_shape[0], dout_shape[2], dout_shape[3], dout_shape[1]]
kernel_h = self.kernel_size[0]
kernel_w = self.kernel_size[1]
stride_h = self.stride[2]
stride_w = self.stride[3]
dilation_h = self.dilation[2]
dilation_w = self.dilation[3]
# default pad mode is valid
pad_list = (0, 0, 0, 0)
if self.pad_list:
pad_list = tuple(self.pad_list)
elif self.pad_mode == "SAME":
pad_needed_h = max(0, (dout_shape_norm[2] - 1) * stride_h + dilation_h * (kernel_h - 1) + 1 - x_size_v[2])
pad_top = math.floor(pad_needed_h / 2)
pad_bottom = pad_needed_h - pad_top
pad_needed_w = max(0, (dout_shape_norm[3] - 1) * stride_w + dilation_w * (kernel_w - 1) + 1 - x_size_v[3])
pad_left = math.floor(pad_needed_w / 2)
pad_right = pad_needed_w - pad_left
pad_list = (pad_top, pad_bottom, pad_left, pad_right)
elif self.pad_mode == 'PAD':
pad_list = self.padding
self.add_prim_attr('pad_list', pad_list)
out = {
'value': None,
'shape': x_size_v,
'dtype': doutput['dtype'],
}
return out
class BiasAdd(PrimitiveWithCheck):
r"""