forked from huawei/mindspore2022
!30321 dynamic shape feed mode
Merge pull request !30321 from Henry Shi/branch_sxy
This commit is contained in:
commit
eaae9961a3
|
|
@ -927,15 +927,19 @@ bool AnfRuntimeAlgorithm::IsIndependentNode(const CNodePtr &node) {
|
|||
}
|
||||
|
||||
static inline void GetMaxOrDefaultShape(const std::vector<int64_t> &max_shape, std::vector<size_t> *device_shape) {
|
||||
constexpr size_t kDefaultValueForDynamicDim = 16;
|
||||
auto ConvertNegOneToDefault = [&kDefaultValueForDynamicDim](size_t size) {
|
||||
return static_cast<int64_t>(size) < 0 ? kDefaultValueForDynamicDim : size;
|
||||
};
|
||||
if (!max_shape.empty()) {
|
||||
(void)std::transform(max_shape.begin(), max_shape.end(), device_shape->begin(), IntToSize);
|
||||
if (device_shape->empty()) {
|
||||
std::transform(max_shape.begin(), max_shape.end(), std::back_inserter(*device_shape), ConvertNegOneToDefault);
|
||||
} else {
|
||||
std::transform(max_shape.begin(), max_shape.end(), device_shape->begin(), IntToSize);
|
||||
}
|
||||
} else {
|
||||
constexpr size_t kDefaultValueForDynamicDim = 16;
|
||||
auto tmp_shape = *device_shape;
|
||||
auto ConvertNegOneToDefalut = [&kDefaultValueForDynamicDim](size_t size) {
|
||||
return static_cast<int64_t>(size) < 0 ? kDefaultValueForDynamicDim : size;
|
||||
};
|
||||
(void)std::transform(tmp_shape.begin(), tmp_shape.end(), device_shape->begin(), ConvertNegOneToDefalut);
|
||||
(void)std::transform(tmp_shape.begin(), tmp_shape.end(), device_shape->begin(), ConvertNegOneToDefault);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -948,7 +952,7 @@ static inline void GetMaxOrDefaultShape(const std::vector<int64_t> &max_shape, s
|
|||
std::vector<size_t> AnfRuntimeAlgorithm::GetInputDeviceShapeAdaptively(const AnfNodePtr &anf_node, size_t index) {
|
||||
auto device_shape = GetInputDeviceShape(anf_node, index);
|
||||
// Initialize GPUKernel with max shape to fit 'InitDynamicOutputKernelRef()' for memory reuse.
|
||||
if (AnfUtils::IsShapeDynamic(device_shape)) {
|
||||
if (AnfUtils::IsShapeDynamic(device_shape) || device_shape.empty()) {
|
||||
auto max_shape = common::AnfAlgo::GetInputMaxShape(anf_node, index);
|
||||
GetMaxOrDefaultShape(max_shape, &device_shape);
|
||||
auto format = GetInputFormat(anf_node, index);
|
||||
|
|
@ -962,7 +966,7 @@ std::vector<size_t> AnfRuntimeAlgorithm::GetInputDeviceShapeAdaptively(const Anf
|
|||
std::vector<size_t> AnfRuntimeAlgorithm::GetOutputDeviceShapeAdaptively(const AnfNodePtr &anf_node, size_t index) {
|
||||
auto device_shape = GetOutputDeviceShape(anf_node, index);
|
||||
// Initialize GPUKernel with max shape to fit 'InitDynamicOutputKernelRef()' for memory reuse.
|
||||
if (AnfUtils::IsShapeDynamic(device_shape)) {
|
||||
if (AnfUtils::IsShapeDynamic(device_shape) || device_shape.empty()) {
|
||||
auto max_shape = common::AnfAlgo::GetOutputMaxShape(anf_node, index);
|
||||
GetMaxOrDefaultShape(max_shape, &device_shape);
|
||||
auto format = GetOutputFormat(anf_node, index);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@ RangePair TbeDynamicShapeUtil::GetInputDynamicRange(const AnfNodePtr &anf_node,
|
|||
}
|
||||
RangePair ret;
|
||||
for (size_t i = 0; i < input_range_min.size(); ++i) {
|
||||
if (input_range_min[i] < 0) {
|
||||
input_range_min[i] = 1;
|
||||
}
|
||||
ret.emplace_back(input_range_min[i], input_range_max[i]);
|
||||
}
|
||||
return shapeRangeTransfer.GetRealRange(ret, format, data_type);
|
||||
|
|
@ -108,6 +111,9 @@ RangePair TbeDynamicShapeUtil::GetOutputDynamicRange(const AnfNodePtr &anf_node,
|
|||
}
|
||||
RangePair ret;
|
||||
for (size_t i = 0; i < output_range_min.size(); ++i) {
|
||||
if (output_range_min[i] < 0) {
|
||||
output_range_min[i] = 1;
|
||||
}
|
||||
ret.emplace_back(output_range_min[i], output_range_max[i]);
|
||||
}
|
||||
return shapeRangeTransfer.GetRealRange(ret, format, data_type);
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ void GetRealInputSize(const nlohmann::json &input_json, std::vector<size_t> *inp
|
|||
if (j >= input_max_shape.size()) {
|
||||
MS_LOG(EXCEPTION) << "Invalid Dynamic Shape Max Shape";
|
||||
}
|
||||
MS_LOG(INFO) << "Change -1 Shape to Max Shape:" << input_max_shape[j][1];
|
||||
(*size_i) = SizetMulWithOverflowCheck((*size_i), LongToSize(input_max_shape[j][1]));
|
||||
MS_LOG(INFO) << "Change -1 Shape to 1:" << input_max_shape[j][1];
|
||||
(*size_i) = SizetMulWithOverflowCheck((*size_i), 1);
|
||||
continue;
|
||||
}
|
||||
(*size_i) = SizetMulWithOverflowCheck((*size_i), static_cast<size_t>(input_json[kJShape][j]));
|
||||
|
|
@ -89,8 +89,8 @@ void GetRealOutputSize(const nlohmann::json &output_json, std::vector<size_t> *o
|
|||
if (j >= output_max_shape.size()) {
|
||||
MS_LOG(EXCEPTION) << "Invalid Dynamic Shape Max Shape";
|
||||
}
|
||||
MS_LOG(INFO) << "Change -1 Shape to Max Shape:" << output_max_shape[j][1];
|
||||
(*size_i) = SizetMulWithOverflowCheck(*size_i, LongToSize(output_max_shape[j][1]));
|
||||
MS_LOG(INFO) << "Change -1 Shape to 1:" << output_max_shape[j][1];
|
||||
(*size_i) = SizetMulWithOverflowCheck(*size_i, 1);
|
||||
continue;
|
||||
}
|
||||
(*size_i) = SizetMulWithOverflowCheck(*size_i, static_cast<size_t>(output_json[kJShape][j]));
|
||||
|
|
|
|||
|
|
@ -415,6 +415,7 @@ void DataPrepareActor::PrepareDataForHostTensorQueue(const std::vector<std::vect
|
|||
AnfAlgo::SetOutputAddr(tensor_address, 0, input_node.get());
|
||||
tensor_address->SetNodeIndex(input_node, 0);
|
||||
}
|
||||
device_address->SetSize(host_tensors[tensor_position]->data().nbytes());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,11 @@ def get_single_io_arg(info):
|
|||
res = info
|
||||
else:
|
||||
res = None
|
||||
if 'range' in info:
|
||||
for i in range(len(info['range'])):
|
||||
if info['range'][i][1] == -1:
|
||||
info['range'][i][1] = None
|
||||
res = info
|
||||
return res
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,10 @@ class Tensor(Tensor_):
|
|||
_check_tensor_input(input_data, dtype, shape, init)
|
||||
|
||||
# If input_data is tuple/list/numpy.ndarray, it's support in check_type method.
|
||||
if init is None:
|
||||
if (isinstance(shape, (list, tuple)) and None in shape) or init is not None:
|
||||
shape = _check_tensor_dynamic_shape(dtype, shape, init)
|
||||
Tensor_.__init__(self, dtype, shape)
|
||||
else:
|
||||
validator.check_value_type('input_data', input_data,
|
||||
(Tensor_, np.ndarray, np.str_, list, tuple, float, int, bool, complex),
|
||||
'Tensor')
|
||||
|
|
@ -153,8 +156,6 @@ class Tensor(Tensor_):
|
|||
Tensor_.__init__(self, input_data, dtype)
|
||||
else:
|
||||
Tensor_.__init__(self, input_data)
|
||||
else:
|
||||
Tensor_.__init__(self, dtype, shape)
|
||||
|
||||
self.virtual_flag = False
|
||||
self.init = init
|
||||
|
|
@ -2898,9 +2899,6 @@ def _check_tensor_input(input_data=None, dtype=None, shape=None, init=None):
|
|||
if init is not None and (shape is None or dtype is None):
|
||||
raise ValueError("init, dtype and shape must have values at the same time.")
|
||||
|
||||
if (int(input_data is None) + int(init is None)) != 1:
|
||||
raise TypeError("input_data and init can not be None at the same time.")
|
||||
|
||||
if input_data is not None:
|
||||
if isinstance(input_data, np.ndarray) and input_data.ndim > 1 and input_data.size == 0:
|
||||
raise ValueError("input_data can not contain zero dimension.")
|
||||
|
|
@ -2912,4 +2910,18 @@ def _check_tensor_input(input_data=None, dtype=None, shape=None, init=None):
|
|||
raise ValueError("Shape can not contain zero value.")
|
||||
|
||||
|
||||
def _check_tensor_dynamic_shape(dtype=None, shape=None, init=None):
|
||||
"""Check if the tensor has dynamic shape."""
|
||||
shape_list = list(shape)
|
||||
if len(shape_list) >= 1:
|
||||
shape_replaced_list = [-1 if i is None else i for i in shape_list]
|
||||
if isinstance(shape, tuple):
|
||||
shape = tuple(shape_replaced_list)
|
||||
if isinstance(shape, list):
|
||||
shape = shape_replaced_list
|
||||
if -1 in shape and (dtype is None or init is not None):
|
||||
raise ValueError("If setting dynamic shape, dtype must not be None, init must be None")
|
||||
return shape
|
||||
|
||||
|
||||
tensor_operator_registry.register('vm_compare', _vm_compare)
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ class Cell(Cell_):
|
|||
self.cast = Cast()
|
||||
self._has_config_recompute = False
|
||||
self._user_parameters = []
|
||||
self._dynamic_shape_inputs = None
|
||||
self.saved_dynamic_shape = None
|
||||
|
||||
def __getstate__(self):
|
||||
base = Cell_.__getstate__(self)
|
||||
|
|
@ -660,7 +662,7 @@ class Cell(Cell_):
|
|||
exist_objs.add(item)
|
||||
if item.name == PARAMETER_NAME_DEFAULT:
|
||||
logger.warning("The parameter definition is deprecated.\n"
|
||||
"Please set a unique name for the parameter in ParameterTuple '{}'.". format(value))
|
||||
"Please set a unique name for the parameter in ParameterTuple '{}'.".format(value))
|
||||
item.name = item.name + "$" + str(self._id)
|
||||
self._id += 1
|
||||
self.insert_param_to_cell(item.name, item, check_name_contain_dot=False)
|
||||
|
|
@ -875,6 +877,40 @@ class Cell(Cell_):
|
|||
self._construct_inputs_names = self._construct_inputs_names[1:self._construct_inputs_num]
|
||||
self._construct_inputs_num = self._construct_inputs_num - 1
|
||||
|
||||
def set_inputs(self, *inputs):
|
||||
"""
|
||||
Save set inputs for computation graph.
|
||||
|
||||
Args:
|
||||
inputs (tuple): Inputs of the Cell object.
|
||||
|
||||
Examples:
|
||||
>>> n = Net()
|
||||
>>> input_dyn = Tensor(shape = [3, None], dtype=type)
|
||||
>>> net.set_inputs(input_dyn)
|
||||
>>> input1 = Tensor(np.random.random([3, 10]), dtype=type)
|
||||
>>> output = net(input1)
|
||||
|
||||
NOTE:
|
||||
This is an experimental interface that is subject to change or deletion.
|
||||
"""
|
||||
|
||||
self._dynamic_shape_inputs = inputs
|
||||
if isinstance(self._dynamic_shape_inputs[0], (str, int, dict)):
|
||||
raise TypeError(f"For 'set_inputs, the type must be tuple, but got {type(self._dynamic_shape_inputs[0])}.")
|
||||
|
||||
def get_inputs(self):
|
||||
"""
|
||||
Returns the dynamic_inputs of a cell object in one network.
|
||||
|
||||
Returns:
|
||||
inputs (tuple): Inputs of the Cell object.
|
||||
NOTE:
|
||||
This is an experimental interface that is subject to change or deletion.
|
||||
"""
|
||||
|
||||
return self._dynamic_shape_inputs
|
||||
|
||||
def compile(self, *inputs):
|
||||
"""
|
||||
Compile Cell as a computation graph, the input must be consistent with the input defined in construct.
|
||||
|
|
@ -882,7 +918,20 @@ class Cell(Cell_):
|
|||
Args:
|
||||
inputs (tuple): Inputs of the Cell object.
|
||||
"""
|
||||
_cell_graph_executor.compile(self, *inputs, phase=self.phase, auto_parallel_mode=self._auto_parallel_mode)
|
||||
if self._dynamic_shape_inputs is None or self._dynamic_shape_inputs[0] is None:
|
||||
_cell_graph_executor.compile(self, *inputs, phase=self.phase, auto_parallel_mode=self._auto_parallel_mode)
|
||||
else:
|
||||
self._check_compile_dynamic_shape(*inputs)
|
||||
if self.saved_dynamic_shape:
|
||||
for i in range(len(self.saved_dynamic_shape)):
|
||||
if self.saved_dynamic_shape[i].shape != self._dynamic_shape_inputs[i].shape \
|
||||
and self.saved_dynamic_shape[i].shape != self._dynamic_shape_inputs[i].shape:
|
||||
break
|
||||
return
|
||||
self.saved_dynamic_shape = self._dynamic_shape_inputs
|
||||
_cell_graph_executor.compile(self, *self._dynamic_shape_inputs, phase=self.phase,
|
||||
auto_parallel_mode=self._auto_parallel_mode)
|
||||
logger.debug("Compiled Graph with dynamic shape")
|
||||
|
||||
def compile_and_run(self, *inputs):
|
||||
"""
|
||||
|
|
@ -911,7 +960,7 @@ class Cell(Cell_):
|
|||
new_inputs.append(i)
|
||||
elif context.get_context("grad_for_scalar") and isinstance(i, (int, float)):
|
||||
new_inputs.append(i)
|
||||
elif hasattr(self, "enable_tuple_broaden") and self.enable_tuple_broaden and isinstance(i, tuple) and\
|
||||
elif hasattr(self, "enable_tuple_broaden") and self.enable_tuple_broaden and isinstance(i, tuple) and \
|
||||
_check_all_tensor(i):
|
||||
new_inputs.append(i)
|
||||
|
||||
|
|
@ -1245,7 +1294,7 @@ class Cell(Cell_):
|
|||
for value, param in self.parameters_and_names():
|
||||
if param.name in names:
|
||||
raise ValueError("The value of {} is {}, its name '{}' already exists. "
|
||||
"Please set a unique name for the parameter.". format(value, param, param.name))
|
||||
"Please set a unique name for the parameter.".format(value, param, param.name))
|
||||
names.add(param.name)
|
||||
|
||||
def parameters_and_names(self, name_prefix='', expand=True):
|
||||
|
|
@ -2073,6 +2122,43 @@ class Cell(Cell_):
|
|||
params.append(param)
|
||||
return params
|
||||
|
||||
def _check_compile_dynamic_shape(self, *inputs):
|
||||
"""
|
||||
Check if graph has been compiled with dynamic shape.
|
||||
|
||||
Args:
|
||||
inputs (tuple): Inputs of the Cell object.
|
||||
"""
|
||||
len_inputs = len(inputs)
|
||||
len_dynamic_shape_inputs = len(self._dynamic_shape_inputs)
|
||||
if len_dynamic_shape_inputs != len_inputs:
|
||||
raise ValueError(
|
||||
f"For 'set_inputs', the Length of Tensor should be {len_inputs}, but got {len_dynamic_shape_inputs}."
|
||||
)
|
||||
for tensor_index in range(len_dynamic_shape_inputs):
|
||||
i_dynamic_shape_inputs = self._dynamic_shape_inputs[tensor_index]
|
||||
i_inputs = inputs[tensor_index]
|
||||
if i_dynamic_shape_inputs.dtype is not i_inputs.dtype:
|
||||
raise TypeError(
|
||||
f"For 'set_inputs', the DataType of Tensor should be {i_inputs.dtype}, but got "
|
||||
f"{i_dynamic_shape_inputs.dtype}."
|
||||
)
|
||||
set_inputs_shape = list(i_dynamic_shape_inputs.shape)
|
||||
inputs_shape = list(i_inputs.shape)
|
||||
if len(inputs_shape) != len(set_inputs_shape):
|
||||
raise ValueError(
|
||||
f"For 'set_inputs' the Dimension of Tensor shape must be {len(inputs_shape)}, but got "
|
||||
f"{len(set_inputs_shape)}."
|
||||
)
|
||||
for shape_index in i_dynamic_shape_inputs.shape:
|
||||
if shape_index != -1:
|
||||
dynamic_index = i_dynamic_shape_inputs.shape.index(shape_index)
|
||||
if set_inputs_shape[dynamic_index] != inputs_shape[dynamic_index]:
|
||||
raise ValueError(
|
||||
f"For 'Length of Tensor shape', the value must be the same with that of inputs, but"
|
||||
f" got {i_dynamic_shape_inputs.shape}."
|
||||
)
|
||||
|
||||
|
||||
class GraphCell(Cell):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -294,6 +294,8 @@ class Model:
|
|||
if self._optimizer is None:
|
||||
# In this case, multiple optimizer(s) is supposed to be included in 'self._network'
|
||||
_set_multi_subgraphs()
|
||||
if self._network.get_inputs() is not None:
|
||||
network.set_inputs(*self._network.get_inputs())
|
||||
return network
|
||||
|
||||
def _build_eval_network(self, metrics, eval_network, eval_indexes):
|
||||
|
|
|
|||
Loading…
Reference in New Issue