!25863 fix dynamic shape bugs

Merge pull request !25863 from fangzehua/fix_dy_1028
This commit is contained in:
i-robot 2021-11-06 07:46:22 +00:00 committed by Gitee
commit a3441bbfb5
19 changed files with 106 additions and 43 deletions

View File

@ -81,7 +81,7 @@ void SliceCPUKernel::InitSliceParam(const std::vector<size_t> &input_shape, cons
slice_size = dim_len - begin_pos;
}
if (slice_size <= 0) {
MS_LOG(EXCEPTION) << "Slice requires the each dimension slice size must be greater than 0.";
MS_LOG(EXCEPTION) << "Slice requires the each dimension slice size must be greater than 0 or be equal to -1.";
}
slice_param_.shape_[i] = dim_len;
slice_param_.size_[i] = slice_size;

View File

@ -32,14 +32,7 @@ constexpr size_t kSliceGradMaxInputShapeSize = 4;
void SliceGradCPUKernel::InitKernel(const CNodePtr &kernel_node) {
MS_EXCEPTION_IF_NULL(kernel_node);
cnode_ptr_ = kernel_node;
begin_.clear();
size_.clear();
strides_.clear();
end_.clear();
input_element_num_.clear();
output_element_num_.clear();
input_shape_.clear();
output_shape_.clear();
ClearVectors();
auto input_shape = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, 0);
if (input_shape.size() > kSliceGradMaxInputShapeSize) {
MS_LOG(EXCEPTION) << "Input dims is " << input_shape.size() << ", but SliceGradCpuKernel only support 4d or lower.";
@ -83,6 +76,17 @@ void SliceGradCPUKernel::InitKernel(const CNodePtr &kernel_node) {
CPUKernelUtils::GetElementNumEveryDim(output_shape_, &output_element_num_);
}
void SliceGradCPUKernel::ClearVectors() {
begin_.clear();
size_.clear();
strides_.clear();
end_.clear();
input_element_num_.clear();
output_element_num_.clear();
input_shape_.clear();
output_shape_.clear();
}
void SliceGradCPUKernel::ExpandAllMemberDims() {
auto output_len = output_shape_.size();
constexpr size_t expand_dims = 4;
@ -107,6 +111,8 @@ void SliceGradCPUKernel::ExpandAllMemberDims() {
void SliceGradCPUKernel::InitParams(const std::vector<kernel::AddressPtr> &inputs) {
auto cnode = cnode_ptr_.lock();
ClearVectors();
output_shape_ = AnfAlgo::GetOutputInferShape(cnode, 0);
std::string kernel_name = AnfAlgo::GetCNodeName(cnode);
auto begin_shape = AnfAlgo::GetPrevNodeOutputInferShape(cnode, 2);
auto begin_ptr = reinterpret_cast<int32_t *>(inputs[2]->addr);
@ -129,7 +135,8 @@ void SliceGradCPUKernel::InitParams(const std::vector<kernel::AddressPtr> &input
[](const int32_t &value) { return value; });
(void)std::transform(end.begin(), end.end(), std::back_inserter(end_), [](const int32_t &value) { return value; });
if (strides_.size() != end_.size() || strides_.size() != output_shape_.size()) {
MS_LOG(EXCEPTION) << "stride|end|input size must be equal";
MS_LOG(EXCEPTION) << "stride|end|input size must be equal, but got begin: " << begin_ << ", size: " << size_
<< ", input shape: " << output_shape_;
}
FormatArgs(true);
} else {

View File

@ -42,6 +42,7 @@ class SliceGradCPUKernel : public CPUKernel {
const std::vector<kernel::AddressPtr> &outputs, size_t out_offset, size_t copy_num,
int id) const;
void InitParams(const std::vector<kernel::AddressPtr> &inputs);
void ClearVectors();
void ExpandAllMemberDims();
bool CanCopyMemoryOnAxis(size_t dim) const;
int SignOfStride(size_t axis) const;

View File

@ -573,7 +573,15 @@ void ConstInputToAttr(const CNodePtr &cnode, const std::unordered_set<size_t> &i
if (i >= input_names_vec.size()) {
MS_LOG(EXCEPTION) << "index " << i << " is larger than input names size [" << input_names_vec.size() << "]";
}
primitive->set_attr(input_names_vec[i], value_node->value());
auto value = value_node->value();
if (value->isa<tensor::Tensor>()) {
auto tensor = value->cast<tensor::TensorPtr>();
if (tensor->data().const_data() == nullptr) {
need_update = false;
break;
}
}
primitive->set_attr(input_names_vec[i], value);
need_update = true;
} else {
new_inputs.push_back(inputs[i + 1]);

View File

@ -683,7 +683,9 @@ EvalResultPtr PythonPrimEvaluator::EvalPrim(const AnalysisEnginePtr &, const Abs
const auto eval_result = evaluator_cache_mgr_->GetValue(args);
if (eval_result != nullptr) {
return eval_result;
auto abs = eval_result->abstract()->Clone();
auto attr = eval_result->attribute();
return std::make_shared<EvalResult>(abs, attr);
}
auto py_args = PreparePyInputs(prim_py_, args);

View File

@ -85,7 +85,13 @@ void KernelActor::Run(OpContext<DeviceTensor> *const context) {
// Infer kernel shape and update abstract info for dynamic shape kernel.
if (is_dynamic_shape_) {
device_contexts_[0]->UpdateDynamicShape(kernel_);
try {
device_contexts_[0]->UpdateDynamicShape(kernel_);
} catch (const std::exception &e) {
MsException::Instance().SetException();
std::string error_info = "Update Dynamic shape exception: " + kernel_->fullname_with_scope();
SET_OPCONTEXT_FAIL_RET_WITH_ERROR_BY_STRATEGY(strategy_, (*context), error_info);
}
}
FetchInputDeviceTensor(context);

View File

@ -94,7 +94,7 @@ AbstractBasePtr InferImplStack(const AnalysisEnginePtr &, const PrimitivePtr &pr
// Inputs: a tuple of tensor.
const std::string op_name = primitive->name();
CheckArgsSize(op_name, args_spec_list, 1);
auto arg = CheckArg<AbstractTuple>(op_name, args_spec_list, 0);
auto arg = CheckArg<AbstractSequeue>(op_name, args_spec_list, 0);
if (arg->elements().empty()) {
MS_LOG(EXCEPTION) << "Arg elements is empty.";
}
@ -838,7 +838,7 @@ AbstractBasePtr InferImplReshape(const AnalysisEnginePtr &, const PrimitivePtr &
if (it_first != shape.end()) {
auto it_second = find(it_first + 1, shape.end(), -1);
if (it_second != shape.end()) {
MS_LOG(EXCEPTION) << "At most one component of input shape can be -1";
MS_LOG(EXCEPTION) << "At most one component of input shape can be -1, but got " << shape;
}
auto index = LongToSize(std::distance(shape.begin(), it_first));
int64_t infer_value = x_num;

View File

@ -98,7 +98,12 @@ std::vector<int64_t> GetDependsFormMap(const CNodePtr &cnode) {
MS_EXCEPTION_IF_NULL(primitive);
auto iter = dynamic_shape_depends.find(primitive->ToString());
if (iter != dynamic_shape_depends.end()) {
return iter->second;
int64_t cnode_input_size = SizeToLong(cnode->inputs().size());
std::vector<int64_t> res;
auto ori = iter->second;
(void)std::copy_if(ori.begin(), ori.end(), std::back_inserter(res),
[&](auto idx) { return idx < cnode_input_size - 1; });
return res;
}
return {};
}
@ -123,6 +128,7 @@ PrimitiveEvalImplMap &GetPrimitiveToEvalImplMap() {
{prim::kPrimReal, {InferImplReal, nullptr, true}},
// Array
{prim::kPrimRange, {InferImplRange, nullptr, true}},
{prim::kPrimStack, {InferImplStack, nullptr, true}},
{prim::kPrimScalarToArray, {InferImplScalarToArray, nullptr, true}},
{prim::kPrimArrayToScalar, {InferImplArrayToScalar, nullptr, true}},
{prim::kPrimBroadcastShape, {InferImplBroadCastShape, nullptr, true}},
@ -255,7 +261,6 @@ PrimitiveEvalImplMap &GetPrimitiveToBackendEvalImplMap() {
{prim::kPrimLinSpace, {InferImplLinSpace, nullptr, true}},
{prim::kPrimLess, {InferImplLess, nullptr, true}},
{prim::kPrimStack, {InferImplStack, nullptr, true}},
{prim::kPrimPad, {InferImplPad, nullptr, true}},
{prim::kPrimUnsortedSegmentSum, {InferImplUnsortedSegmentSum, nullptr, true}},
{prim::kPrimDiv, {InferImplDiv, nullptr, true}},

View File

@ -35,6 +35,7 @@ abstract::ShapePtr SliceInferShape(const PrimitivePtr &primitive, const std::vec
MS_EXCEPTION_IF_NULL(item);
}
auto shape_map = CheckAndConvertUtils::ConvertShapePtrToShapeMap(input_args[0]->BuildShape());
auto input_shape = shape_map[kShape];
auto min_shape = shape_map[kMinShape];
auto max_shape = shape_map[kMaxShape];
std::vector<std::vector<int64_t>> input_values;
@ -47,13 +48,25 @@ abstract::ShapePtr SliceInferShape(const PrimitivePtr &primitive, const std::vec
} else {
tmp_input = CheckAndConvertUtils::CheckAttrTupleInt("slice args value", input_value, prim_name);
}
(void)input_values.emplace_back(tmp_input);
}
if (max_shape.empty() && min_shape.empty()) {
return std::make_shared<abstract::Shape>(input_values[1]);
auto begin_v = input_values[0];
auto size_v = input_values[1];
auto rank = input_shape.size();
if (begin_v.size() != rank || size_v.size() != rank) {
MS_LOG(EXCEPTION) << "For Slice, the shape of input|begin|size must be equal.";
}
return std::make_shared<abstract::Shape>(input_values[1], min_shape, max_shape);
for (size_t i = 0; i < size_v.size(); ++i) {
if (size_v[i] == -1) {
size_v[i] = input_shape[i] - begin_v[i];
}
}
if (max_shape.empty() && min_shape.empty()) {
return std::make_shared<abstract::Shape>(size_v);
}
return std::make_shared<abstract::Shape>(size_v, min_shape, max_shape);
}
TypePtr SliceInferType(const PrimitivePtr &prim, const std::vector<AbstractBasePtr> &input_args) {

View File

@ -69,6 +69,12 @@ abstract::ShapePtr TileInferShape(const PrimitivePtr &primitive, const std::vect
multiples_v = CheckAndConvertUtils::CheckAttrTupleInt("tile multiples value", multiple_value, prim_name);
}
for (auto multiple : multiples_v) {
if (multiple <= 0) {
MS_LOG(EXCEPTION) << "multiples in Tile should be an int and must > 0, but got " << multiples_v;
}
}
auto infer_shape = GetInferShape(input_shape, multiples_v);
if (max_shape.empty() && min_shape.empty()) {
return std::make_shared<abstract::Shape>(infer_shape);

View File

@ -247,6 +247,7 @@ def _tile_shape(multiples, shapex):
else:
ret.append(1)
ret.append(shapex[j])
j += 1
len_cmp += 1
return tuple(ret)
@ -262,24 +263,33 @@ def get_bprop_tile(self):
def bprop(x, multiples, out, dout):
shapex = shape_op(x)
if isinstance(multiples, tuple):
if -1 in shapex:
shapex = dyn_shape_op(x)
# if shapex or multiples not tuple, it should be dynamic shape.
if isinstance(multiples, tuple) and isinstance(shapex, tuple):
r_shape = _tile_shape(multiples, shapex)
else:
if isinstance(multiples, tuple):
multiples = tuple_to_array(multiples)
multiples = cast(multiples, mstype.int64)
len_multi = size_op(multiples)
rank = len(shapex)
shape_tensor = cast(tuple_to_array(shapex), mstype.int64)
if isinstance(shapex, tuple):
shape_tensor = cast(tuple_to_array(shapex), mstype.int64)
else:
shape_tensor = shapex
if len_multi > rank:
one_tensor = ones((len_multi - rank,), mstype.int64)
shape_tensor = concat((shape_tensor, one_tensor))
shape_tensor = concat((one_tensor, shape_tensor))
elif len_multi < rank:
one_tensor = ones((rank - len_multi,), mstype.int64)
multiples = concat((multiples, one_tensor))
multiples = concat((one_tensor, multiples))
tile_shape = stack_op((multiples, shape_tensor))
r_shape = reshape(tile_shape, (-1,))
r_shape = P.Reshape()(tile_shape, (-1,))
# 0 represents the start index, and 2 represents the step
axis = F.make_range(0, len(r_shape), 2)
dx = reduce_sum(reshape(dout, r_shape), axis)
dx = reduce_sum(P.Reshape()(dout, r_shape), axis)
dx = reshape(dx, shapex)
return dx, zeros_like(multiples)

View File

@ -7,4 +7,4 @@ j
bprop.6:x*
bprop.6:out*
bprop.6:dout2
bprop.6:[CNode]:2:@dae47635340bc244097f692e3d086cc9ae28fd823d60946e421051e28dbccdadP
bprop.6:[CNode]:2:@8e2475d2a78429b63ff06e217cb14568f5d5fe5054a046c67278551d2456d5ccP

View File

@ -7,4 +7,4 @@ j
bprop.7:x*
bprop.7:out*
bprop.7:dout2
bprop.7:[CNode]:2:@dae47635340bc244097f692e3d086cc9ae28fd823d60946e421051e28dbccdadP
bprop.7:[CNode]:2:@8e2475d2a78429b63ff06e217cb14568f5d5fe5054a046c67278551d2456d5ccP

View File

@ -5,4 +5,4 @@ d
bprop.2:x*
bprop.2:out*
bprop.2:dout2
bprop.2:[CNode]:1:@dae47635340bc244097f692e3d086cc9ae28fd823d60946e421051e28dbccdadP
bprop.2:[CNode]:1:@8e2475d2a78429b63ff06e217cb14568f5d5fe5054a046c67278551d2456d5ccP

View File

@ -7,4 +7,4 @@ i
bprop.4:x*
bprop.4:out*
bprop.4:dout2
bprop.4:[CNode]:2:@dae47635340bc244097f692e3d086cc9ae28fd823d60946e421051e28dbccdadP
bprop.4:[CNode]:2:@8e2475d2a78429b63ff06e217cb14568f5d5fe5054a046c67278551d2456d5ccP

View File

@ -7,4 +7,4 @@ i
bprop.3:x*
bprop.3:out*
bprop.3:dout2
bprop.3:[CNode]:2:@dae47635340bc244097f692e3d086cc9ae28fd823d60946e421051e28dbccdadP
bprop.3:[CNode]:2:@8e2475d2a78429b63ff06e217cb14568f5d5fe5054a046c67278551d2456d5ccP

View File

@ -7,4 +7,4 @@ i
bprop.5:x*
bprop.5:out*
bprop.5:dout2
bprop.5:[CNode]:2:@dae47635340bc244097f692e3d086cc9ae28fd823d60946e421051e28dbccdadP
bprop.5:[CNode]:2:@8e2475d2a78429b63ff06e217cb14568f5d5fe5054a046c67278551d2456d5ccP

View File

@ -2001,19 +2001,16 @@ class Tile(PrimitiveWithInfer):
def __infer__(self, x, multiples):
multiples_v = multiples['value']
if multiples_v is None:
if len(multiples['shape']) != 1:
raise ValueError(f'For \'{self.name}\' the dim of multiples must be 1.')
rank = max(len(x['shape']), multiples['shape'][0])
out_shape = [-1] * rank
if 'max_shape' not in x:
max_shape = x['shape']
min_shape = x['shape']
else:
max_shape = x['max_shape']
min_shape = x['min_shape']
# tile can't infer min/max shape if multiples_v is None
return {'shape': out_shape,
'dtype': x['dtype'],
'value': None,
'min_shape': min_shape,
'max_shape': max_shape
'min_shape': [1] * rank,
'max_shape': [1] * rank
}
x_shp = x['shape']
@ -2856,7 +2853,13 @@ class Slice(PrimitiveWithInfer):
x_shp_len = len(x_shape)
begin_v, size_v = begin['value'], size['value']
if begin_v is None or size_v is None:
out_shape = [-1] * size['shape'][0]
# if size_v is not None and begin_v is None, it should be also a dynamic output shape.
if size_v is None:
if size['shape'][0] < 0:
raise ValueError(f"For '{self.name}', the size shape haven't support dynamic yet.")
out_shape = [-1] * size['shape'][0]
else:
out_shape = [-1] * len(size_v)
if 'max_shape' in x:
max_shape = x['max_shape']
min_shape = x['min_shape']

View File

@ -487,7 +487,9 @@ class _Reduce(PrimitiveWithInfer):
if np_reduce_func is not None:
value = input_x['value'].asnumpy()
if not axis_v:
if isinstance(axis_v, int):
axis_v = (axis_v,)
elif not axis_v:
axis_v = [i for i in range(len(input_x['shape']))]
axis_v = tuple(axis_v)
value = np_reduce_func(value, axis_v, keepdims=self.keep_dims)