mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-20 19:12:24 +00:00
Merge
This commit is contained in:
commit
3ccb0876fd
5 changed files with 275 additions and 26 deletions
1
CODEOWNERS
Normal file
1
CODEOWNERS
Normal file
|
|
@ -0,0 +1 @@
|
|||
@Microsoft/onnxruntime
|
||||
|
|
@ -104,6 +104,229 @@ The quantization formula is y = (x / y_scale) + y_zero_point. For (x / y_scale),
|
|||
The linear de-quantization operator. It consumes a quantized data, a scale, a zero point and computes the full precision data.
|
||||
The dequantization formula is y = (x - x_zero_point) * x_scale.
|
||||
Scale and zero point must have same shape. They must be either scalar (per tensor) or 1-D tensor (per 'axis').)DOC");
|
||||
|
||||
const char* auto_pad_doc =
|
||||
"auto_pad must be either NOTSET, SAME_UPPER, SAME_LOWER or VALID. Where "
|
||||
"default value is NOTSET, which means explicit padding is used. "
|
||||
"SAME_UPPER or SAME_LOWER mean pad the input so that the output size match the input."
|
||||
"In case of odd number add the extra padding at the end for SAME_UPPER and at the "
|
||||
"beginning for SAME_LOWER. VALID mean no padding.";
|
||||
|
||||
ONNX_CONTRIB_OPERATOR_SCHEMA(QLinearConv)
|
||||
.SetDomain(kMSDomain)
|
||||
.SinceVersion(1)
|
||||
.SetDoc(R"DOC(
|
||||
The convolution operator consumes a quantized input tensor, its scale and zero point,
|
||||
a quantized filter, its scale and zero point, and output’s scale and zero point,
|
||||
and computes the quantized output. Each scale and zero point pair must have same shape.
|
||||
It means they must be either scalars (per tensor) or 1-D tensors (per channel).)DOC")
|
||||
.Input(
|
||||
0,
|
||||
"x",
|
||||
"Input data tensor from previous layer; "
|
||||
"has size (N x C x H x W), where N is the batch size, "
|
||||
"C is the number of channels, and H and W are the "
|
||||
"height and width. Note that this is for the 2D image. "
|
||||
"Otherwise the size is (N x C x D1 x D2 ... x Dn). "
|
||||
"Optionally, if dimension denotation is "
|
||||
"in effect, the operation expects input data tensor "
|
||||
"to arrive with the dimension denotation of [DATA_BATCH, "
|
||||
"DATA_CHANNEL, DATA_FEATURE, DATA_FEATURE ...].",
|
||||
"T1")
|
||||
.Input(1, "x_scale", "Scale tensor for input ‘x’. It could be a scalar or a 1-D tensor, which means a per-tensor or per-channel quantization. If it’s a 1-D tensor, its number of elements should be equal to the number of channels of input ‘x’.", "T3")
|
||||
.Input(2, "x_zero_point", "Zero point tensor for input ‘x’. It could be a scalar or a 1-D tensor, which means a per-tensor or per-channel quantization. If it’s a 1-D tensor, its number of elements should be equal to the number of channels of input ‘x’.", "T1")
|
||||
.Input(
|
||||
3,
|
||||
"w",
|
||||
"The weight tensor that will be used in the "
|
||||
"convolutions; has size (M x C/group x kH x kW), where C "
|
||||
"is the number of channels, and kH and kW are the "
|
||||
"height and width of the kernel, and M is the number "
|
||||
"of feature maps. For more than 2 dimensions, the "
|
||||
"kernel shape will be (M x C/group x k1 x k2 x ... x kn), "
|
||||
"where (k1 x k2 x ... kn) is the dimension of the kernel. "
|
||||
"Optionally, if dimension denotation is in effect, "
|
||||
"the operation expects the weight tensor to arrive "
|
||||
"with the dimension denotation of [FILTER_OUT_CHANNEL, "
|
||||
"FILTER_IN_CHANNEL, FILTER_SPATIAL, FILTER_SPATIAL ...]. "
|
||||
"X.shape[1] == (W.shape[1] * group) == C "
|
||||
"(assuming zero based indices for the shape array). "
|
||||
"Or in other words FILTER_IN_CHANNEL should be equal to DATA_CHANNEL. ",
|
||||
"T1")
|
||||
.Input(4, "w_scale", "Scale tensor for input ‘w’. It could be a scalar or a 1-D tensor, which means a per-tensor or per-channel quantization. If it’s a 1-D tensor, its number of elements should be equal to the number of channels of input ‘w’.", "T3")
|
||||
.Input(5, "w_zero_point", "Scale tensor for input ‘w’. It could be a scalar or a 1-D tensor, which means a per-tensor or per-channel quantization. If it’s a 1-D tensor, its number of elements should be equal to the number of channels of input ‘w’.", "T1")
|
||||
.Input(6, "y_scale", "Scale tensor for output ‘y’. It could be a scalar or a 1-D tensor, which means a per-tensor or per-channel quantization. If it’s a 1-D tensor, its number of elements should be equal to the number of channels of input ‘y’.", "T3")
|
||||
.Input(7, "y_zero_point", "Scale tensor for output ‘y’. It could be a scalar or a 1-D tensor, which means a per-tensor or per-channel quantization. If it’s a 1-D tensor, its number of elements should be equal to the number of channels of input ‘y’.", "T1")
|
||||
.Input(8, "B", "Optional 1D bias to be added to the convolution, has size of M.", "T2", OpSchema::Optional)
|
||||
.Output(
|
||||
0,
|
||||
"y",
|
||||
"Output data tensor that contains the result of the "
|
||||
"convolution. The output dimensions are functions "
|
||||
"of the kernel size, stride size, and pad lengths.",
|
||||
"T1")
|
||||
.TypeConstraint(
|
||||
"T1",
|
||||
{"tensor(int8)", "tensor(uint8)"},
|
||||
"Constrain input, filter, and output types to 8-bit integer tensors.")
|
||||
.TypeConstraint("T2", {"tensor(int32)", "tensor(uint32)"}, "Constrain bias type to 32-bit integer tensor.")
|
||||
.TypeConstraint("T3", {"tensor(float)"}, "Constrain scale of input, filter and output to float tensor.")
|
||||
.Attr(
|
||||
"auto_pad",
|
||||
auto_pad_doc,
|
||||
AttributeProto::STRING,
|
||||
std::string("NOTSET"))
|
||||
.Attr(
|
||||
"kernel_shape",
|
||||
"The shape of the convolution kernel. If not present, should be inferred from input 'w'.",
|
||||
AttributeProto::INTS,
|
||||
OPTIONAL)
|
||||
.Attr(
|
||||
"dilations",
|
||||
"dilation value along each axis of the filter. If not present, the dilation defaults to 1 along each axis.",
|
||||
AttributeProto::INTS,
|
||||
OPTIONAL)
|
||||
.Attr(
|
||||
"strides", "Stride along each axis. If not present, the stride defaults to 1 along each axis.", AttributeProto::INTS, OPTIONAL)
|
||||
.Attr("pads",
|
||||
"Padding for the beginning and ending along each axis, it can take any value greater than or equal to 0."
|
||||
"The value represent the number of pixels added to the beginning and end part of the corresponding axis."
|
||||
"`pads` format should be as follow [x1_begin, x2_begin...x1_end, x2_end,...], where xi_begin the number of"
|
||||
"pixels added at the beginning of axis `i` and xi_end, the number of pixels added at the end of axis `i`."
|
||||
"This attribute cannot be used simultaneously with auto_pad attribute. If not present, the padding defaults"
|
||||
"to 0 along start and end of each axis.",
|
||||
AttributeProto::INTS, OPTIONAL)
|
||||
.Attr(
|
||||
"group",
|
||||
"number of groups input channels and output channels are divided into. default is 1.",
|
||||
AttributeProto::INT,
|
||||
static_cast<int64_t>(1));
|
||||
|
||||
ONNX_CONTRIB_OPERATOR_SCHEMA(ConvInteger)
|
||||
.SetDomain(kMSDomain)
|
||||
.SinceVersion(1)
|
||||
.SetDoc(R"DOC(
|
||||
The integer convolution operator consumes an input tensor, a filter, and a padding value,
|
||||
and computes the output. The production MUST never overflow. The accumulation may overflow
|
||||
if and only if in 32 bits.)DOC")
|
||||
.Input(
|
||||
0,
|
||||
"x",
|
||||
"Input data tensor from previous layer; "
|
||||
"has size (N x C x H x W), where N is the batch size, "
|
||||
"C is the number of channels, and H and W are the "
|
||||
"height and width. Note that this is for the 2D image. "
|
||||
"Otherwise the size is (N x C x D1 x D2 ... x Dn). "
|
||||
"Optionally, if dimension denotation is "
|
||||
"in effect, the operation expects input data tensor "
|
||||
"to arrive with the dimension denotation of [DATA_BATCH, "
|
||||
"DATA_CHANNEL, DATA_FEATURE, DATA_FEATURE ...].",
|
||||
"T1")
|
||||
.Input(
|
||||
1,
|
||||
"w",
|
||||
"The weight tensor that will be used in the "
|
||||
"convolutions; has size (M x C/group x kH x kW), where C "
|
||||
"is the number of channels, and kH and kW are the "
|
||||
"height and width of the kernel, and M is the number "
|
||||
"of feature maps. For more than 2 dimensions, the "
|
||||
"kernel shape will be (M x C/group x k1 x k2 x ... x kn), "
|
||||
"where (k1 x k2 x ... kn) is the dimension of the kernel. "
|
||||
"Optionally, if dimension denotation is in effect, "
|
||||
"the operation expects the weight tensor to arrive "
|
||||
"with the dimension denotation of [FILTER_OUT_CHANNEL, "
|
||||
"FILTER_IN_CHANNEL, FILTER_SPATIAL, FILTER_SPATIAL ...]. "
|
||||
"X.shape[1] == (W.shape[1] * group) == C "
|
||||
"(assuming zero based indices for the shape array). "
|
||||
"Or in other words FILTER_IN_CHANNEL should be equal to DATA_CHANNEL. ",
|
||||
"T2")
|
||||
.Input(2, "z", "Padding value (zero_point normally), it's optional and default value is 0.", "T1", OpSchema::Optional)
|
||||
.Output(
|
||||
0,
|
||||
"y",
|
||||
"Output data tensor that contains the result of the "
|
||||
"convolution. The output dimensions are functions "
|
||||
"of the kernel size, stride size, and pad lengths.",
|
||||
"T1")
|
||||
.TypeConstraint("T1", {"tensor(int8)", "tensor(uint8)"}, "Constrain input X and Z data types as 8-bit integer tensors")
|
||||
.TypeConstraint("T2", {"tensor(int8)", "tensor(uint8)"}, "Constrain input W data types as 8-bit integer tensor")
|
||||
.TypeConstraint("T3",
|
||||
{"tensor(int32)", "tensor(uint32)"},
|
||||
"Constrain output Y data types as 32-bits integer tensors."
|
||||
"T3 must be tensor(uint32) when both T1 and T2 are tensor(uint8),"
|
||||
"or must be tensor(int32) when either T1 or T2 is tensor(int8).")
|
||||
.Attr(
|
||||
"auto_pad",
|
||||
auto_pad_doc,
|
||||
AttributeProto::STRING,
|
||||
std::string("NOTSET"))
|
||||
.Attr(
|
||||
"kernel_shape",
|
||||
"The shape of the convolution kernel. If not present, should be inferred from input 'w'.",
|
||||
AttributeProto::INTS,
|
||||
OPTIONAL)
|
||||
.Attr(
|
||||
"dilations",
|
||||
"dilation value along each axis of the filter. If not present, the dilation defaults to 1 along each axis.",
|
||||
AttributeProto::INTS,
|
||||
OPTIONAL)
|
||||
.Attr(
|
||||
"strides", "Stride along each axis. If not present, the stride defaults to 1 along each axis.", AttributeProto::INTS, OPTIONAL)
|
||||
.Attr("pads",
|
||||
"Padding for the beginning and ending along each axis, it can take any value greater than or equal to 0."
|
||||
"The value represent the number of pixels added to the beginning and end part of the corresponding axis."
|
||||
"`pads` format should be as follow [x1_begin, x2_begin...x1_end, x2_end,...], where xi_begin the number of"
|
||||
"pixels added at the beginning of axis `i` and xi_end, the number of pixels added at the end of axis `i`."
|
||||
"This attribute cannot be used simultaneously with auto_pad attribute. If not present, the padding defaults"
|
||||
"to 0 along start and end of each axis.",
|
||||
AttributeProto::INTS, OPTIONAL)
|
||||
.Attr(
|
||||
"group",
|
||||
"number of groups input channels and output channels are divided into. default is 1.",
|
||||
AttributeProto::INT,
|
||||
static_cast<int64_t>(1));
|
||||
|
||||
ONNX_CONTRIB_OPERATOR_SCHEMA(MatMulInteger)
|
||||
.SetDomain(kMSDomain)
|
||||
.SinceVersion(1)
|
||||
.SetDoc(R"DOC(
|
||||
Matrix product that behaves like numpy.matmul: https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.matmul.html.
|
||||
The production MUST never overflow. The accumulation may overflow if and only if in 32 bits.)DOC")
|
||||
.Input(0, "A", "N-dimensional matrix A", "T1")
|
||||
.Input(0, "B", "N-dimensional matrix B", "T2")
|
||||
.Output(0, "Y", "Matrix multiply results from A * B", "T3")
|
||||
.TypeConstraint("T1", {"tensor(int8)", "tensor(uint8)"}, "Constrain input A data types as 8-bit integer tensor")
|
||||
.TypeConstraint("T2", {"tensor(int8)", "tensor(uint8)"}, "Constrain input B data types as 8-bit integer tensor")
|
||||
.TypeConstraint("T3",
|
||||
{"tensor(int32)", "tensor(uint32)"},
|
||||
"Constrain output Y data types as 32-bit integer tensor."
|
||||
"T3 must be tensor(uint32) when both T1 and T2 are tensor(uint8),"
|
||||
"or must be tensor(int32) when either T1 or T2 is tensor(int8).");
|
||||
|
||||
ONNX_CONTRIB_OPERATOR_SCHEMA(ReduceSumInteger)
|
||||
.SetDomain(kMSDomain)
|
||||
.SinceVersion(1)
|
||||
.SetDoc(R"DOC(
|
||||
Computes the sum of the low-precision input tensor's element along the provided axes.
|
||||
The resulting tensor has the same rank as the input if keepdims equal 1. If keepdims equal 0,
|
||||
then the resulting tensor have the reduced dimension pruned. The above behavior is similar to numpy,
|
||||
with the exception that numpy default keepdims to False instead of True.)DOC")
|
||||
.Input(0, "data", "An input tensor.", "T1")
|
||||
.Output(0, "reduced", "Reduced output tensor.", "T2")
|
||||
.TypeConstraint("T1", {"tensor(int8)", "tensor(uint8)"}, "Constrain input type to 8-bit integer tensor.")
|
||||
.TypeConstraint("T2",
|
||||
{"tensor(int32)", "tensor(uint32)"},
|
||||
"Constrain output data type to 32-bit integer tensor."
|
||||
"T2 must be tensor(uint32) when T1 is tensor(uint8),"
|
||||
"or must be tensor(int32) when T1 is tensor(int8).")
|
||||
.Attr(
|
||||
"axes",
|
||||
"A list of integers, along which to reduce. The default is to reduce over all the dimensions of the input tensor.",
|
||||
AttributeProto::INTS)
|
||||
.Attr(
|
||||
"keepdims",
|
||||
"Keep the reduced dimension or not, default 1 mean keep reduced dimension.",
|
||||
AttributeProto::INT);
|
||||
}
|
||||
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, float, SampleOp);
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ MLValueTensorSlicer<T> MLValueTensorSlicer<T>::Create(T& mlvalue, int64_t slice_
|
|||
ONNXRUNTIME_ENFORCE(mlvalue.IsAllocated(), "MLValue has not been allocated so can't be sliced.");
|
||||
|
||||
auto& tensor_shape{mlvalue.template Get<Tensor>().Shape()};
|
||||
ONNXRUNTIME_ENFORCE(gsl::narrow_cast<int64_t>(tensor_shape.NumDimensions()) > slice_dimension,
|
||||
"Insufficient dimensions to slice on ", slice_dimension, ". Shape:", tensor_shape);
|
||||
ONNXRUNTIME_ENFORCE(gsl::narrow_cast<int64_t>(tensor_shape.NumDimensions()) >= slice_dimension,
|
||||
"Insufficient dimensions to slice on ", slice_dimension, ". Shape:", tensor_shape);
|
||||
|
||||
auto dim0_size = tensor_shape[0];
|
||||
ONNXRUNTIME_ENFORCE(dim0_offset < dim0_size, "Invalid dim0_offset of ", dim0_offset, ". Dimension 0 is ", dim0_size);
|
||||
|
|
|
|||
|
|
@ -516,9 +516,10 @@ static const MLValue& GetSubgraphInputMLValue(const OpKernelContextInternal& con
|
|||
// Validate that the subgraph input has valid shapes
|
||||
Status ScanImpl::ValidateSubgraphInput(int start_input, int end_input, bool is_loop_state_var,
|
||||
const std::vector<const NodeArg*>& graph_inputs) {
|
||||
// first dim is batch size. optional sequence dim. dim/s for the data
|
||||
// first dim is batch size. optional sequence dim. dim/s for the data.
|
||||
// if there is no dim for the data treat it as a scalar.
|
||||
bool has_seq_len_dim = !is_loop_state_var;
|
||||
auto min_dims_required = has_seq_len_dim ? 3 : 2;
|
||||
auto min_dims_required = has_seq_len_dim ? 2 : 1;
|
||||
|
||||
for (int i = start_input; i < end_input; ++i) {
|
||||
auto& input_tensor = GetSubgraphInputTensor(context_, i);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ struct RunOptions {
|
|||
bool include_dim_values_in_subgraph = true;
|
||||
bool include_types_in_subgraph = true;
|
||||
bool include_outer_scope_add = false;
|
||||
bool scalar_loop_state_value = false;
|
||||
bool add_bad_shape = false;
|
||||
};
|
||||
|
||||
|
|
@ -37,13 +38,13 @@ class ScanOpTester : public OpTester {
|
|||
// add outer_scope_0 node. push the value through an extra Identity node as a Constant gets lifted into an
|
||||
// initializer which results in different treatment by the allocation planner
|
||||
{
|
||||
TypeProto float_scalar;
|
||||
float_scalar.mutable_tensor_type()->set_elem_type(TensorProto_DataType_FLOAT);
|
||||
auto mutable_dim = float_scalar.mutable_tensor_type()->mutable_shape()->add_dim();
|
||||
TypeProto float_single_value;
|
||||
float_single_value.mutable_tensor_type()->set_elem_type(TensorProto_DataType_FLOAT);
|
||||
auto mutable_dim = float_single_value.mutable_tensor_type()->mutable_shape()->add_dim();
|
||||
mutable_dim->set_dim_value(1);
|
||||
|
||||
{
|
||||
auto& outer_scope_constant = graph.GetOrCreateNodeArg("outer_scope_constant", &float_scalar);
|
||||
auto& outer_scope_constant = graph.GetOrCreateNodeArg("outer_scope_constant", &float_single_value);
|
||||
auto* constant = graph.AddNode("outer_scope_constant", "Constant", "Constant with value kOuterNodeAddValue",
|
||||
{}, {&outer_scope_constant});
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ class ScanOpTester : public OpTester {
|
|||
|
||||
constant->AddAttribute("value", value_tensor);
|
||||
|
||||
auto& outer_scope_node_arg = graph.GetOrCreateNodeArg("outer_scope_0", &float_scalar);
|
||||
auto& outer_scope_node_arg = graph.GetOrCreateNodeArg("outer_scope_0", &float_single_value);
|
||||
graph.AddNode("outer_scope_id", "Identity", "Identity for outer_scope_0",
|
||||
{&outer_scope_constant}, {&outer_scope_node_arg});
|
||||
}
|
||||
|
|
@ -66,7 +67,7 @@ class ScanOpTester : public OpTester {
|
|||
};
|
||||
|
||||
static void CreateSubgraph(Graph& graph, RunOptions& options, const std::string& failure_message) {
|
||||
bool include_shapes = options.include_dim_values_in_subgraph;
|
||||
bool include_dim_values = options.include_dim_values_in_subgraph;
|
||||
bool include_types = options.include_types_in_subgraph;
|
||||
|
||||
std::vector<NodeArg*> inputs;
|
||||
|
|
@ -94,21 +95,27 @@ static void CreateSubgraph(Graph& graph, RunOptions& options, const std::string&
|
|||
inputs = {};
|
||||
outputs = {};
|
||||
|
||||
TypeProto float_scalar;
|
||||
TypeProto float_input;
|
||||
// inputs must have type information and a rank
|
||||
float_scalar.mutable_tensor_type()->set_elem_type(TensorProto_DataType_FLOAT);
|
||||
auto mutable_dim = float_scalar.mutable_tensor_type()->mutable_shape()->add_dim();
|
||||
if (include_shapes)
|
||||
mutable_dim->set_dim_value(1);
|
||||
float_input.mutable_tensor_type()->set_elem_type(TensorProto_DataType_FLOAT);
|
||||
auto mutable_shape = float_input.mutable_tensor_type()->mutable_shape();
|
||||
if (options.scalar_loop_state_value) {
|
||||
// no dims
|
||||
} else {
|
||||
auto mutable_dim = mutable_shape->add_dim(); // set rank
|
||||
if (include_dim_values)
|
||||
mutable_dim->set_dim_value(1);
|
||||
}
|
||||
|
||||
{
|
||||
auto& output_arg = graph.GetOrCreateNodeArg("constant_1", &float_scalar);
|
||||
auto& output_arg = graph.GetOrCreateNodeArg("constant_1", &float_input);
|
||||
outputs.push_back(&output_arg);
|
||||
|
||||
auto* constant = graph.AddNode("constant", "Constant", "Constant with value 1", inputs, outputs);
|
||||
|
||||
TensorProto value_tensor;
|
||||
value_tensor.add_dims(1);
|
||||
if (!options.scalar_loop_state_value)
|
||||
value_tensor.add_dims(1);
|
||||
value_tensor.add_float_data(1.f);
|
||||
value_tensor.set_data_type(onnx::TensorProto_DataType_FLOAT);
|
||||
|
||||
|
|
@ -118,7 +125,7 @@ static void CreateSubgraph(Graph& graph, RunOptions& options, const std::string&
|
|||
inputs = outputs; // start with output from Constant node
|
||||
outputs = {};
|
||||
|
||||
auto& input_arg = graph.GetOrCreateNodeArg("loop_state_in_1", &float_scalar);
|
||||
auto& input_arg = graph.GetOrCreateNodeArg("loop_state_in_1", &float_input);
|
||||
inputs.push_back(&input_arg);
|
||||
|
||||
TypeProto loop_state_output_tensor;
|
||||
|
|
@ -128,15 +135,17 @@ static void CreateSubgraph(Graph& graph, RunOptions& options, const std::string&
|
|||
// it has to come from here.
|
||||
bool type_and_shape_required = options.include_dim_values_in_main_graph == false;
|
||||
|
||||
if (include_shapes || type_and_shape_required)
|
||||
loop_state_output_tensor.mutable_tensor_type()->mutable_shape()->add_dim()->set_dim_value(1);
|
||||
if (include_dim_values || type_and_shape_required) {
|
||||
mutable_shape = loop_state_output_tensor.mutable_tensor_type()->mutable_shape();
|
||||
if (!options.scalar_loop_state_value)
|
||||
mutable_shape->add_dim()->set_dim_value(1);
|
||||
}
|
||||
|
||||
TypeProto* type_proto = include_types || type_and_shape_required ? &loop_state_output_tensor : nullptr;
|
||||
auto& output_arg = graph.GetOrCreateNodeArg("loop_state_out_1", type_proto);
|
||||
outputs.push_back(&output_arg);
|
||||
|
||||
auto* add = graph.AddNode("add", "Add", "Add 1 to the loop state", inputs, outputs);
|
||||
(void)add;
|
||||
graph.AddNode("add", "Add", "Add 1 to the loop state", inputs, outputs);
|
||||
}
|
||||
|
||||
// subgraph with multiple inputs and outputs to test variadic behaviour.
|
||||
|
|
@ -152,7 +161,7 @@ static void CreateSubgraph(Graph& graph, RunOptions& options, const std::string&
|
|||
// inputs must have type information and rank, but dimension can have no value if we're not providing shape info.
|
||||
concat_input_tensor.mutable_tensor_type()->set_elem_type(TensorProto_DataType_FLOAT);
|
||||
auto mutable_dim = concat_input_tensor.mutable_tensor_type()->mutable_shape()->add_dim();
|
||||
if (include_shapes) {
|
||||
if (include_dim_values) {
|
||||
mutable_dim->set_dim_value(2);
|
||||
|
||||
if (options.add_bad_shape) {
|
||||
|
|
@ -168,7 +177,7 @@ static void CreateSubgraph(Graph& graph, RunOptions& options, const std::string&
|
|||
// one output from concatenate of {4} tensor
|
||||
TypeProto concat_output_tensor;
|
||||
concat_output_tensor.mutable_tensor_type()->set_elem_type(TensorProto_DataType_FLOAT);
|
||||
if (include_shapes)
|
||||
if (include_dim_values)
|
||||
concat_output_tensor.mutable_tensor_type()->mutable_shape()->add_dim()->set_dim_value(4);
|
||||
|
||||
TypeProto* type_proto = include_types ? &concat_output_tensor : nullptr;
|
||||
|
|
@ -277,13 +286,18 @@ void RunTest(const std::string test_name, int64_t batch_size, int64_t max_sequen
|
|||
|
||||
test.AddShapeToTensorData(options.include_dim_values_in_main_graph);
|
||||
|
||||
test.AddInput<float>("scan_loop_state_in_0", {batch_size, 1}, loop_state_in_0);
|
||||
std::vector<int64_t> loop_state_shape{batch_size};
|
||||
if (!options.scalar_loop_state_value) {
|
||||
loop_state_shape.push_back(1);
|
||||
}
|
||||
|
||||
test.AddInput<float>("scan_loop_state_in_0", loop_state_shape, loop_state_in_0);
|
||||
|
||||
std::vector<int64_t> input_shape{batch_size, max_sequence_len, input_size};
|
||||
test.AddInput<float>("scan_input_0", input_shape, input_0);
|
||||
test.AddInput<float>("scan_input_1", input_shape, input_1);
|
||||
|
||||
test.AddOutput<float>("scan_loop_state_out_0", {batch_size, 1}, loop_state_out_0);
|
||||
test.AddOutput<float>("scan_loop_state_out_0", loop_state_shape, loop_state_out_0);
|
||||
|
||||
std::vector<int64_t> output_shape{batch_size, max_sequence_len, 1};
|
||||
test.AddOutput<float>("scan_output_0", output_shape, output_0);
|
||||
|
|
@ -353,6 +367,16 @@ TEST(Scan, ShortSequenceOneInBatchOneLoopStateVar_NoShapeInMainGraph_NoTypeAndSh
|
|||
ShortSequenceOneInBatchOneLoopStateVar(options);
|
||||
}
|
||||
|
||||
TEST(Scan, OnnxScalarLoopState) {
|
||||
RunOptions options{};
|
||||
options.include_dim_values_in_main_graph = true;
|
||||
options.include_types_in_subgraph = false;
|
||||
options.include_dim_values_in_subgraph = false;
|
||||
options.scalar_loop_state_value = true;
|
||||
|
||||
ShortSequenceOneInBatchOneLoopStateVar(options);
|
||||
}
|
||||
|
||||
// test when there is an operator in the subgraph that uses a value coming from outer scope
|
||||
TEST(Scan, OuterScopeAccess_NoShapeInMainGraph_TypeAndShapeInSubgraph) {
|
||||
RunOptions options{};
|
||||
|
|
|
|||
Loading…
Reference in a new issue